我试图了解 SQL Server 2016 SP3 系统上的一些执行计划缓存元数据,但我无法将看到的内容与文档相协调。
文档sys.dm_exec_cached_plans
说它包含:
SQL Server 为加快查询执行而缓存的每个查询计划的一行。
在我观察的系统上,这个视图现在有 41,283 行。其中绝大多数(37,594 行)是 cacheobjtype = "Compiled Plan" 和 objtype = "Adhoc"。
文档sys.dm_exec_query_stats
说它包含:
缓存计划中的每个查询语句一行,并且行的生命周期与计划本身相关联。当从缓存中删除计划时,相应的行将从该视图中删除。
我希望此视图中至少有 37,594 行(每个缓存计划一个,如果某些缓存计划有多个语句,则可能更多)。但是,此视图总共有 6,867 行。
这种差异是如此之大,以至于我必须假设我误解了这些观点应该是什么。
sys.dm_exec_query_stats
有人可以帮我理解为什么与 相比有这么少的行sys.dm_exec_cached_plans
吗?
我尝试在 上将表内部连接在一起plan_handle
,唯一的匹配是 1:1 - 换句话说,有数以万计的缓存计划没有“查询统计”行。
我还认为这种差异可能是由许多行在sys.dm_exec_procedure_stats
or中来解释的sys.dm_exec_trigger_stats
,但事实并非如此(分别为 93 行和 2 行)。
对于任何对这个问题的“为什么”感到好奇的人,我想看看缓存中的各种计划有多老,除了加入sys.dm_exec_query_stats
和检查之外,我不确定有什么方法可以做到这一点creation_time
。
以下是我用来获取上述数字的查询:
-- total cached plans
SELECT COUNT_BIG(*) AS total_cached_plans
FROM sys.dm_exec_cached_plans decp
-- totals by type
SELECT decp.cacheobjtype, decp.objtype, COUNT_BIG(*) AS plan_count
FROM sys.dm_exec_cached_plans decp
GROUP BY decp.cacheobjtype, decp.objtype
ORDER BY decp.cacheobjtype, decp.objtype;
-- total query stats
SELECT COUNT_BIG(*) AS total_query_stats
FROM sys.dm_exec_query_stats;
这些查询绝大多数是未参数化的用户查询,而不是系统查询。我通过按 SQL 文本(从 中提取)排序来验证这一点sys.dm_exec_sql_text
。一些例子:
- 5,000 条不同的“INSERT INTO”语句针对具有不同文字值的同一张表
- 具有不同 WHERE 子句的 15,000 个不同的“SELECT COUNT(*)”查询
- 针对具有不同文字值的几个表的 15,000 个不同的“更新”语句
这些都是连接到该服务器的应用程序提交的合法查询。
您的许多查询都符合简单参数化的条件。
SQL Server 创建语句的参数化版本并将其缓存为准备好的计划。
您看到的临时计划只是指向参数化版本的shell 。
中的条目
sys.dm_exec_query_stats
仅与准备好的计划相关联。有关更多背景信息,请参阅我的文章Simple Parameterization and Trivial Plans。