I mentioned that servers receiving a lot of dynamic constructs (typically those generated by client SQL generaters/ORM/LINQ, etc.) can start to consume too much plan cache and have problems with "single-use plans" in my last post titled: Statement execution and why you should use stored procedures. I also mentioned that SQL Server 2008 has an option/feature specifically to help reduce the bloat on the plan cache by only storing a query plan hash the first time a plan is created.
First – let's check to see how your plan cache is currently allocated:
(note: updated to decimal(18,2) as a few of you had overflow errors due to high use counts!)
SELECT objtype AS [CacheType]
, count_big(*) AS [Total Plans]
, sum(cast(size_in_bytes as decimal(18,2)))/1024/1024 AS [Total MBs]
, avg(usecounts) AS [Avg Use Count]
, sum(cast((CASE WHEN usecounts = 1 THEN size_in_bytes ELSE 0 END) as decimal(18,2)))/1024/1024 AS [Total MBs - USE Count 1]
, sum(CASE WHEN usecounts = 1 THEN 1 ELSE 0 END) AS [Total Plans - USE Count 1]
FROM sys.dm_exec_cached_plans
GROUP BY objtype
ORDER BY [Total MBs - USE Count 1] DESC
go
This statement will show you how much of your cache is allocated to single use plans… and, I'd love to hear what your numbers are… this query works in 2005 and 2008; however, the primary solution I'm describing here (optimize for adhoc workloads) will only work in SQL Server 2008.
If you have a lot of your cache going to plans that are only executed once, then it's time to clean up the cache and take better advantage of it with plans that are more consistent and more stable. Ideally, this means using more stored procedures and writing these stored procedures effectively for better performance (I'm currently in the midst of doing this in my Optimizing Procedural Code category). However, if you absolutely must use a lot of adhoc SQL, then you should consider upgrading and turning on this new option. It's an advanced configuration option so you won't see it until you "show advanced options" and it's set using sp_configure. There have been some other really good posts out there on how to use this and what this is so I'm just going to bring together some great resources for you to read. The most important post to read (and it's especially important for those on you on versions of SQL Server 2000 or SQL Server 2005 RTM/SP1 [er... why aren't you on SP2?]) is that plan cache can get out of control. 2005 SP2 and 2008 reduce the total size but there no upper limit (which is again – a GREAT reason for the addition of "optimize for adhoc workloads"). Kalen Delaney talks about how things really work in her SQL Server 2005 SP2 post titled: Did You Know? SP2 does NOT limit the amount of plan cache you can have (key word there is LIMIT). Again, SQL Server doesn't set an upper limit but it does [drastically] reduce the total size that's possible (as of SP2). As for even more details on plan caching, recompilation and SQL Server 2008's better cache control – check out Greg Low's (blog|twitter) whitepaper titled: Plan Caching in SQL Server 2008. Taken STRAIGHT from the first section of the whitepaper:
SQL Server 2008 and SQL Server 2005 SP2
* 75% of visible target memory from 0-4GB + 10% of visible target memory from 4Gb-64GB + 5% of visible target memory > 64GB
SQL Server 2005 RTM and SQL Server 2005 SP1
* 75% of visible target memory from 0-8GB + 50% of visible target memory from 8Gb-64GB + 25% of visible target memory > 64GB
SQL Server 2000
* SQL Server 2000 4GB upper cap on the plan cache
Finally, lots of additional posts on this topic will give you even more details:
- Bob Beauchemin (blog) did a simple post on this while it was still in RC0 here: Performance features in SQL Server 2008 RC0 – Optimize for Adhoc Workloads.
- Jose Barreto (blog|twitter) did a simple post on this and pulls together a few nice resources as well here: SQL Server 2008 Optimize for Ad Hoc Workloads.
- Kalen Delaney (blog) did a post on how SQL Server 2008's metadata returns only 17 characters when "Compiled Plan Stub" is actually 18… and, how to correctly see it here: Geek City: Reducing Cache Bloat and a Metadata Bug. Note: this bug has been fixed in SQL Server 2008 SP1.
- Kalen Delaney wrote an article on SQL Server Magazine (note: this article requires a SQL Server Magazine subscription) titled: Managing Plan Cache Size and after the article, she posted a Q&A on the questions she received from the article in a blog post titled: Geek City: Q & A on my Plan Cache Sizing article in SQL Server Magazine.
- Books online topics:
- Glenn [Alan] Berry (blog|twitter) has a post in his DMV A Day series on looking at the plan cache and seeing which statements are causing you grief. Once you see how much cache is being wasted with your single use plans (with the above query) – it's time to start looking and seeing what they are. His blog post is titled: A DMV A Day – Day 16.
However, I'm still really interested in seeing your numbers from the query above – let me know!
NEW/ADDITIONAL REQUEST: Let me know your max server memory setting as well as the total memory available on the box?
Thanks for reading!
kt
30 Responses to Plan cache and optimizing for adhoc workloads
Hello Kimberly, here are my numbers !
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Prepared 2021 620.531250 195 265.601562 895
Adhoc 1557 57.023437 678 28.718750 811
Proc 210 35.992187 7000 4.523437 31
UsrTab 8 0.710937 1002 0.421875 3
Check 15 0.492187 2 0.257812 8
Trigger 7 1.351562 6 0.000000 0
View 113 14.742187 5 0.000000 0
I was unaware of this option and found your latest posts on the subject very, very valuable.
Thanks for that.
Kind Regards,
Olivier.
Very relevant post Kimberly. We should be encouraging people to be on SQL Server 2005 SP3 (since SP2 is an "unsupported service pack"), and the same situation with moving from SQL Server 2008 RTM to SQL Server 2008 SP1. I have been using "optimize for ad-hoc workloads" for over a year with very good results. I will send you my numbers.
Cool. Thanks Glenn. I suspect that a lot of folks have moved to this BUT I also suspect even more folks to be using things like LINQ and be completely unaware of this very necessary option. So… while there have been a lot of great posts about using this (and how to use it), I still wonder how bad some servers really are?? Hence the request! Your servers are probably going to be in a pretty good state but I wonder how many 2 or 3s there are? I’ve always wondered if this shouldn’t have been configurable? Where you should set it at 5 – or 10 before SQL Server would store the plan.
In fact, I wonder if I shouldn’t create some other columns (plan cache dedicated to the "under 10 executions") for example? Thoughts?
Regardless, we’ll get some good insight from averages. Really looking forward to the numbers! And, I’ll compile a bit of details from the numbers I receive as well.
Cheers Glenn!!
kt
My numbers:
Prepared 236 77.718750 261 68.578125 150
Adhoc 1415 68.640625 389 42.093750 491
Proc 289 47.109375 139355 7.335937 32
UsrTab 1 0.070312 1 0.070312 1
Trigger 3 0.281250 35 0.000000 0
View 362 31.859375 18 0.000000 0
Check 5 0.101562 15 0.000000 0
Here is our PROD DWH totals. it is an SQL Server 2005 SP3 Standard Edition. Loading(ELT) is done using a lot of SP’s but querying is adhoc using SAP business objects.
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 2906 122.812500 24 77.078125 1911
Prepared609 98.062500 106 75.593750 360
Proc 53 23.734375 4115 15.390625 25
View 52 3.593750 93 0.000000 0
Check 2 0.031250 5 0.000000 0
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 10107 240.273437 76 157.507812 6073
PrepareD 1442 48.984375 3826 4.750000 106
Proc 44 13.367187 442322 0.742187 2
Trigger 2 0.718750 38 0.000000 0
View 20 1.867187 5 0.000000 0
Here is the query off of our Production Sql Server 2005 SP3 Enterprise (Clustered) server.
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 17028 1255.601562 185 1160.851562 15845
Prepared 22566 838.789062 357 99.867187 505
Proc 561 186.039062 9677 20.414062 51
Check 392 13.296875 10 5.468750 174
UsrTab 3 0.281250 7 0.117187 1
Trigger 7 2.820312 130391 0.000000 0
View 313 32.031250 17 0.000000 0
Here’s one that will skew your results. This is a SQL 2008 server with Optimize for adhoc workloads enabled.
Adhoc 32085 896.078544 77 111.710937 14123
Prepared 2771 178.304687 1682 80.890625 867
Proc 231 54.812500 8145 1.382812 7
UsrTab 1 0.218750 1 0.218750 1
View 802 91.257812 338 0.070312 1
Trigger 25 4.093750 972 0.046875 1
Production server #s:
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 8865 507.632812 6 293.976562 4738
Trigger 330 286.507812 439 40.890625 46
Prepared 1623 109.015625 99 23.687500 393
Proc 922 186.781250 356 22.242187 114
UsrTab 129 2.070312 2 1.070312 65
Check 20 0.312500 5 0.078125 5
Rule 41 0.320312 6 0.046875 6
View 492 18.625000 41 0.000000 0
Well… it’s not surprising that so many of you who read my blog have servers that aren’t in too bad of shape. There are still MBs of useless cache and you’ll want to clean that up for you but nothing’s quite as bad (so far) as one system I’m seeing right now that has over 7GB of single plan cache sitting wasted.
Even in email the worst I’m seeing is a couple hundred MB. It’s the people that aren’t reading this blog for whom I’m worried! (tell your friends to check their servers – friends don’t let friends waste GBs of cache!)
Keep em coming!
Cheers,
kt
Hey there Darrel – Not too bad… and yes, a few folks sent me email with their numbers (from 2008 – with Optimize for adhoc workloads set) and all of these are better. But, stll seems like a lot of wasted cache!
And, @SQLSVRMan – You’ve got over a GB. But, you’re running 2005 SP3 so it’s probably better than it may have been in earlier releases/SPs. You still might want to throw out cache periodically.
Thanks for the numbers!! (and keep ‘em coming – I want to see a clear winner (for worst cache) here :))
Cheers,
kt
Actually, another good point (thanks stalker woman – you know who you are :) :) :))… thanks for telling me the system memory.
That’s another thing to add to your numbers – let me know how much memory the box has on it. I just received an email where a server has over 1.5GB of wasted cache on a system with only 12GB. Those are not good percentages.
Thanks!!
kt
Ha!! Lightweights!! :)
I posted my results in a blog post of my own (which points back to here). I also made a slight modification of the query so that it outputs a Totals line at the bottom. My results are in a easy to read table there, but just to give you an idea, I have 50,745 total single-use plans in cache.
My post: http://www.sqlservercentral.com/blogs/robert_davis/archive/2010/04/23/Looking-forward-to-Optimize-for-Ad-hoc-Workloads-in-Sql-Server-2008.aspx
@Robert-I responded to your post. Excellent numbers! But, not yet the winner (sadly)… I have one customer at over 7GB of "single plan cache" and over 77K of single-use plans in cache. This is on a 2005 SP3 server with 128GB of memory.
THANKS!!!
kt
2008 sp1 DW server 104Gb DB memory
Prepared 5580 3544.414062 190561 874.382812 1968
Adhoc 9871 935.804687 116 681.539062 7711
Proc 438 286.289062 283497 10.203125 30
UsrTab 29 2.140625 3545 0.437500 2
Trigger 4 0.195312 3 0.070312 1
View 1513 171.937500 272 0.054687 1
Check 15 0.359375 15 0.000000 0
Hi Kimberly,
Thanks for the link. I think you meant to link to this post instead, its A DMV a Day – Day 16
http://glennberrysqlperformance.spaces.live.com/blog/cns!45041418ECCAA960!5190.entry
Whoopps! OK, got it. Updated the post with Day 16!
Thanks Glenn!
kt
Hello,
Here my results :
CacheType Total Plans Total MBs Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 126954 3769.070312 1751.523437 61037
Prepared 32423 964.687500 376.570312 9775
Proc 2784 1235.664062 67.195312 186
Check 1114 26.281250 0.187500 8
Trigger 27 5.523437 0.156250 2
View 4265 490.335937 0.000000 0
UsrTab 6 0.539062 0.000000 0
Sorry no AVG => Msg 8115, Level 16, State 2, Line 2
Arithmetic overflow error converting expression to data type int.
I’ve no enough time to check why.
Win2K8 SQL2K8 2node failover cluster
2 instances (result just for one of them)
160 Gb RAM
32 cores
Chris
avg(cast(usecounts as bigint)) AS [Avg Use Count]
UsrTab,2,0.437500,0.000000,0
Prepared,11711,1247.304687,834.093750,2179
View,3884,405.367187,0.000000,0
Adhoc,148326,1043.029365,251.200576,128662
Check,24,0.679687,0.312500,10
Trigger,136,22.390625,0.453125,5
Proc,567,256.390625,55.125000,
sql server 2008 – 256GB. adhoc and forced parametrization enabled
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 6210 264.039062 1278 130.742187 4584
Prepared 1488 152.843750 1391 103.382812 985
Proc 137 121.187500 96624 4.093750 10
UsrTab 1 0.117187 38 0.000000 0
View 663 61.929687 172 0.000000 0
Check 4 0.109375 8 0.000000 0
Trigger 2 0.171875 108 0.000000 0
SQL Server 2005 Enterprise Total memory 24 GB, Max set to default
Here are my numbers on a SQL Server 2005 SP3 box with 7.5GB of total system memory all of which is available to SQL Server. This is an OLTP system that is almost exclusively queried in an ad-hoc manner.
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 4904 322.437500 67 150.906250 1887
Prepared 4493 348.250000 196 40.937500 423
Proc 440 103.179687 1964 8.523437 33
UsrTab 15 0.343750 123 0.140625 2
View 311 15.648437 62 0.031250 1
We have a SQL Server 2005. I’m not sure of the other details. Our data is:
Prepared3332 277.445312 73 150.976562 1594
Adhoc 6566 295.554687 22 122.406250 2866
View 808 66.421875 69 28.250000 301
Proc 347 92.992187 13288 16.562500 35
Trigger 74 41.492187 96 3.078125 10
Check 32 0.679687 11 0.031250 2
UsrTab 4 0.117187 37 0.000000 0
I don’t know if this is really good or bad. One thing to note about our system is that we regularly reboot every weekend. I’m running this on a Wednesday. I wonder how bad it would get if we did not reboot.
Hi Here are my numbers
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 12033 672.148437 34 605.484375 8925
Proc 82 51.273437 18310 2.445312 8
Prepared 23 0.867187 4068 0.085937 3
Trigger 2 0.187500 177 0.000000 0
View 10 1.031250 16 0.000000 0
UsrTab 1 0.015625 20257 0.000000 0
I just want to know the meaning of each columns also tell me these no.s are good or bad?
How to cleanup cache?
Running an active/active 2008R2 cluster, optimize for adhoc workloads not set…
Instance 1
Prepared 20210 3080.640625 12070 967.109375 6339
Adhoc 12174 427.820312 13038 228.796875 5114
Proc 1692 533.078125 1221659 46.812500 177
Trigger 100 18.453125 568372 0.679687 8
UsrTab 23 2.289062 2936 0.406250 3
View 863 102.671875 132 0.101562 2
Check 35 2.109375 24 0.093750 3
SQL Min Mem 12288 SQL Max Mem 24576 Server Total Mem 32767 Server Available Mem 16384
Instance 2
Adhoc 663 39.757812 3 16.398437 319
Proc 222 39.335937 47 15.421875 92
Prepared 203 14.500000 53 8.585937 126
Trigger 13 1.945312 3 0.937500 6
Check 33 0.867187 2 0.460937 16
UsrTab 10 0.804687 7 0.218750 1
View 105 15.687500 4 0.000000 0
SQL Min Mem 12288 SQL Max Mem 24576 Server Total Mem 32767 Server Available Mem 16384
I’m not sure enabling this setting would do much for me right now, however, when I move to virtual servers and right size the memory this could make a big difference.
[...] and potentially wasted cache due to the single-use plans created (see the most recent posts titled:Plan cache and optimizing for adhoc workloads and Plan cache, adhoc workloads and clearing the single-use plan cache bloat). To be more [...]
SQL 2008 Stnd SP3 – Max server memory not set – total mem avail on the box: very little!!!
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Prepared 206 45.414062 1475 26.781250 67
Adhoc 251 28.828125 227 23.687500 163
Proc 205 50.789062 5740 3.062500 11
UsrTab 2 0.234375 4 0.015625 1
View 187 21.187500 10 0.000000 0
Trigger 7 0.742187 17 0.000000 0
Check 21 0.476562 276 0.000000 0
sql 2008 SP3. 192gig memory. 8 cpu
running sharepoint. and Adhoc is OFFFFFFF!
Preprd 29186 5692.820312 1394 877.804687 2859
Adhoc 45327 1837.726562 868 677.226562 14129
Proc 5831 1954.671875 326949 143.578125 371
Check 708 26.687500 2829 8.882812 239
Trigger 87 8.257812 5496 1.062500 15
View 3255 368.625000 4460 0.140625 2
UsrTab 43 4.664062 5909 0.109375 1
Oh, you’ll love this…
Microsoft SQL Server 2008 R2 (SP1) – 10.50.2811.0 (X64)
Apr 6 2012 01:59:29
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.1 (Build 7601: Service Pack 1)
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Prepared 49062 3353.921875 161 2885.164062 44042
Adhoc 67883 4593.289062 94 2781.453125 43294
Proc 2147 1099.031250 18476 26.843750 75
Trigger 88 52.359375 4828 1.898437 3
Check 23 0.632812 479 0.031250 1
View 495 73.882812 1613 0.000000 0
UsrTab 3 0.460937 3 0.000000 0
This is from another server in my client’s environment (SQL 2012 RTM, 24GB RAM, Max memory not set)
CacheType Total Plans Total MBs Avg Use Count Total MBs – USE Count 1 Total Plans – USE Count 1
Adhoc 57243 2264.148437 44 1375.453125 46200
Prepared 11293 764.054687 113 30.851562 201
Proc 433 449.390625 12026 7.218750 15
UsrTab 4 0.078125 1963 0.000000 0
View 1497 144.070312 202 0.000000 0
Check 59 1.679687 350 0.000000 0
Trigger 4 0.226562 96 0.000000 0