SQL Server 2008 had introduced a new feature that helps optimizing ad hoc workloads. SQL server generates an execution plan for each and every statement that’s executed. The reason is that the SQL server would be able to re-use the execution plan when the statement run next time.

However, there are lot of scenario where we execute some statements only once and never again especially when troubleshooting some issues. The plans created for the one time queries occupy the memory and other resources which could be avoided.

Lets see how the SQL Server behaves when adhoc optimization is not enabled.

I have a sample query here that uses the AdventureWorks database, remember *NOT* to run these queries on a production systems. This will clear out the cache what could affect your systems performance.

DBCC freeproccache;
DBCC dropcleanbuffers;
go
SELECT FROM sales.salesorderheader
go
SELECT CP.usecounts,
       CP.cacheobjtype,
       CP.objtype,
       PT.text
FROM sys.dm_exec_cached_plans CP
CROSS apply sys.dm_exec_sql_text(plan_handle) PT
WHERE PT.text LIKE '%select * from Sales.SalesOrderHeader%'
  AND pt.text NOT LIKE
    '%SELECT CP.usecounts, CP.cacheobjtype, CP.objtype, PT.TEXT%'; 

Though the query is executed only once, the plan is cached by the SQL Server for future use. Also look at the size in bytes for a simple one line query, as the query becomes bigger the plan size also would increase.

Adhoc_Workload_1

SQL Server introduced an option to optimize your SQL server for adhoc workloads. You can enable this option using the sp_configure

sp_configure 'optimize for ad hoc workloads', 1
RECONFIGURE

Now run the earlier queries again and see if the plan cache is still getting stored.

DBCC freeproccache;
DBCC dropcleanbuffers;
go
SELECT FROM sales.salesorderheader
go
SELECT CP.usecounts,
       CP.cacheobjtype,
       CP.objtype,
       PT.text
FROM sys.dm_exec_cached_plans CP
CROSS apply sys.dm_exec_sql_text(plan_handle) PT
WHERE PT.text LIKE '%select * from Sales.SalesOrderHeader%'
  AND pt.text NOT LIKE
     '%SELECT CP.usecounts, CP.cacheobjtype, CP.objtype, PT.TEXT%'; 

You will notice that cacheobjecttype is Compiled Plan Stub and the size has reduced considerably. The stubs are not actual plans, you can consider them as a simple skeleton of the execution plan and stubs consume very less size, so your cache wasted in storing these plans will be very less.

Adhoc_Workload_2

We will run the queries once again, but lets run it multiple times(3 times here), and then we will look at the plan size and cacheobjecttype.

DBCC freeproccache;
DBCC dropcleanbuffers;
go
SELECT * FROM sales.salesorderheader
go 3

SELECT CP.usecounts,
       CP.size_in_bytes,
       CP.cacheobjtype,
       CP.objtype,
       PT.text
FROM sys.dm_exec_cached_plans CP
CROSS apply sys.dm_exec_sql_text(plan_handle) PT
WHERE  PT.text LIKE '%select * from Sales.SalesOrderHeader%'
AND pt.text NOT LIKE
'%SELECT CP.usecounts, CP.cacheobjtype, CP.objtype, PT.TEXT%';
go

When we executed the query multiple times, the SQL Server assumed that that it can reuse the plan and then decided to store the execution plan.

Adhoc_Workload_3

References
http://technet.microsoft.com/en-us/library/cc645587.aspx
http://blogs.technet.com/b/josebda/archive/2009/03/19/optimize-for-ad-hoc-workloads-in-sql-server-2008.aspx

 

Leave a Reply

Your email address will not be published. Required fields are marked *