执行计划缓存
执行计划编译是需要时间的,为了提高效用率,是要缓存的,可用如下方式查看:
–查看执行计划的缓存
SELECT UseCounts,RefCounts, Cacheobjtype, Objtype,dbid, ISNULL(DB_NAME(dbid),'ResourceDB') AS DatabaseName, TEXT AS SQL FROM sys.dm_exec_cached_plans CROSS APPLY sys.dm_exec_sql_text(plan_handle) ORDER BY dbid,usecounts DESC; SELECT cacheobjtype,objtype,sql FROM sys.syscacheobjects a WHERE cacheobjtype = 'compiled plan' AND dbid = 7
–清空执行计划缓存
DBCC FREEPROCCACHE
GO
–从缓存中清除给定数据库的计划缓存
DBCC FLUSHPROCINDB(<dbid>)
GO
执行计划重新编译放到缓存中的时机:
1,表或视图的架构发生了更改,索引发生了改变造成统计信息发生更改。
2,运行了sp_recompile
3,执行计划被清除,如服务器重启,服务重启,放在内存中的执行计划就会被清空。
4,缓存会用LRU算法找出很少使用的,然后从内存中删除,在sys.dm_exec_query_stats中有一字段creation_time标识计划的创建时间,一般一、两个小时就会重新建立一份的。
可通过观察以下事件看缓存的变更。SP:CacheInsert SP:CacheMiss SP:CacheHit
执行计划要保持重用,以提高利用率,可以查出经常重新编译的sql以做优化,当然重用并不一定好,因为执行计划不适合,如参数化问题等。
sys.dm_exec_query_stats 有一个栏位plan_generation_num,计划编译次数,可用此来分析最常编译的计划。 select top 25 plan_generation_num, SUBSTRING(qt.text,qs.statement_start_offset/2+1, (case when qs.statement_end_offset = -1 then DATALENGTH(qt.text) else qs.statement_end_offset end -qs.statement_start_offset)/2 + 1) as stmt_executing, qt.text, execution_count, sql_handle, dbid, db_name(dbid) DBName, objectid, object_name(objectid,dbid) ObjectName from sys.dm_exec_query_stats as qs Cross apply sys.dm_exec_sql_text(sql_handle) qt where plan_generation_num >1 --AND qs.last_execution_time >='2011-08-28 10:00' 限定时间 order by plan_generation_num desc