With Or Without You
One thing I really hate about Standard Edition is the lack of a way to globally reduce the allowed memory grant default.
Out of the box, any query can come along and ask for ~25% of your server’s max server memory setting, and SQL Server is willing to loan out ~75% at once across a bunch of queries.
That impacts Standard Edition users way more than Enterprise Edition users, because of the Standard Edition buffer pool limit of 128GB.
A lot of folks misinterpret that limit — I’ve had several exchanges with big name hardware vendors where they insist 128GB is the overall RAM limit, so you’re likely getting bad advice from everywhere — and they end up with a server that only has 128GB of RAM in it.
Big mistake. Bump that up to 192GB and set Max Server Memory to ~180GB or so.
But I digress. Or whatever the word if for getting back to the real point.
I forget, if I ever knew.
For all you high rollers out there on Enterprise Edition, you have an easy way to fight against SQL Server’s bad memory grant habits.
Before we do that, it’s important to make a few notes here:
- SQL Server introduced batch mode memory grant feedback in 2016
- SQL Server introduced batch mode on row store in 2019
Depending on your compatibility level, you may not be taking advantage of those things, but in either case the feedback might be kicking in too late. See, it’s not a runtime decision, it’s a decision that takes place after a query runs.
By then, it’s already sucked up 25% of your memory and probably stolen a whole bunch of space from your precious buffer pool. A properly filled buffer pool is important so your queries don’t get dry-docked going out to slowpoke disk all the live long day.
A lot of the time, folks I work with will have a ton of queries asking for bunk memory grants that are way bigger than they should be.
You can use this query to examine your plan cache for those things.
WITH unused AS ( SELECT TOP (100) oldest_plan = MIN(deqs.creation_time) OVER(), newest_plan = MAX(deqs.creation_time) OVER(), deqs.statement_start_offset, deqs.statement_end_offset, deqs.plan_handle, deqs.execution_count, deqs.max_grant_kb, deqs.max_used_grant_kb, unused_grant = deqs.max_grant_kb - deqs.max_used_grant_kb, deqs.min_spills, deqs.max_spills FROM sys.dm_exec_query_stats AS deqs WHERE (deqs.max_grant_kb - deqs.max_used_grant_kb) > 1024. AND deqs.max_grant_kb > 5242880. ORDER BY unused_grant DESC ) SELECT plan_cache_age_hours = DATEDIFF ( HOUR, u.oldest_plan, u.newest_plan ), query_text = ( SELECT [processing-instruction(query)] = SUBSTRING ( dest.text, ( u.statement_start_offset / 2 ) + 1, ( ( CASE u.statement_end_offset WHEN -1 THEN DATALENGTH(dest.text) ELSE u.statement_end_offset END - u.statement_start_offset ) / 2 ) + 1 ) FOR XML PATH(''), TYPE ), deqp.query_plan, u.execution_count, u.max_grant_kb, u.max_used_grant_kb, u.min_spills, u.max_spills, u.unused_grant FROM unused AS u OUTER APPLY sys.dm_exec_sql_text(u.plan_handle) AS dest OUTER APPLY sys.dm_exec_query_plan(u.plan_handle) AS deqp ORDER BY u.unused_grant DESC OPTION (RECOMPILE, MAXDOP 1);
If you have a bunch of those, and you want a quick fix until you can do more meaningful query and index tuning, you can use Resource Governor to reduce the 25% default to a lower number.
Scripted, For Your Pleasure
You can use this script to enable and reconfigure Resource Governor to use a lower memory grant percent.
/*The first time enables Resource Governor*/ ALTER RESOURCE GOVERNOR RECONFIGURE; /*This reduces the memory grant cap to 10%*/ ALTER WORKLOAD GROUP [default] WITH ( REQUEST_MAX_MEMORY_GRANT_PERCENT = ? ); /*This completes the change*/ ALTER RESOURCE GOVERNOR RECONFIGURE;
You’ll have to fill in the question mark yourself, of course. Without looking at your system, I have no idea what it should be.
If you’d like help with that, hit the link below to schedule a sales call.
Thanks for reading!
If this is the kind of SQL Server stuff you love learning about, you’ll love my training. I’m offering a 75% discount to my blog readers if you click from here. I’m also available for consulting if you just don’t have time for that and need to solve performance problems quickly.