从 sys.dm_exec_query_stats 中删除了关键查询计划,而保留了琐碎的项目

rom*_*n m 2 sql-server plan-cache sql-server-2019

运行 SQL Server Express 2019。

有一个包含 11 条 sql 语句的复杂存储过程(当从sys.dm_exec_query_statsby 中选择时plan_handle)。

其中 9 个语句是基于传入参数的简单变量设置,最后 2 个语句 ( IF/ELSE) 完成所有工作并返回数据(例如query_hash0x111... 和 0x222...)。

基于输入参数的数据量有很大的可变性,所以我用最佳值“准备”存储过程以确保快速执行。

我注意到每隔几天(有时更频繁),我的最后 2 个语句(query_hash0x111...和 ​​0x222...)被转储sys.dm_exec_query_stats,然后根据下一个存储过程中来自用户的任何参数重新生成称呼。

我通过查看creation_time列知道这一点,它反映了前 9 个查询的“启动”时间,以及query_hash0x111... 和 0x222...的稍后时间。

据我了解,缓存计划在内存压力下被清除,较少使用的计划首先被清除。我的查询被大量使用,并且我有很多其他缓存计划,其中 1 次执行会持续一段时间。

问题:为什么我最常用的查询会转储表单缓存,我该如何阻止它发生?

Dav*_*oft 8

我用最佳值“准备”存储过程

你可以做得更好。

而是打开查询存储并强制执行您想要的计划。

或者使用诸如 OPTION (RECOMPILE) 或 OPTIMIZE FOR 之类的查询提示。


Jos*_*ell 7

语句可能被重新编译的原因有很多,包括性能和正确性相关的原因。

例如,查询使用的索引可能已被删除,在这种情况下,必须重新编译计划,因为它确实无法在该状态下运行。

或者统计信息可能已经更新到足以进行自动重新编译。

根据服务器上的负载,以及此语句真正重新编译的频率,您可能能够使用此扩展事件会话捕获实际原因:

CREATE EVENT SESSION [recompiles] ON SERVER 
ADD EVENT sqlserver.sql_statement_recompile
(
    WHERE ([sqlserver].[query_hash]=(111))
)
ADD TARGET package0.event_file (SET filename=N'recompiles')
WITH (STARTUP_STATE=OFF)
Run Code Online (Sandbox Code Playgroud)

这将在系统上的每次重新编译时触发,但只会存储具有与您放入过滤器中的内容匹配的查询哈希的那些。

需要明确的是:不要开始这件事然后去周末。在测试系统上试一下,在生产中试一下,确保它不会太具有破坏性,等等。不要为了追踪这个而关闭你的服务器

如果有帮助,XE 在 SQL Server 2019 上定义了所有这些语句重新编译的原因:

SELECT map_value
FROM sys.dm_xe_map_values
WHERE [name] = N'statement_recompile_cause';
Run Code Online (Sandbox Code Playgroud)
地图值
架构已更改
统计数据已更改
延迟编译
设置选项更改
临时表已更改
远程行集已更改
对于已更改的浏览权限
查询通知环境已更改
分区视图已更改
光标选项已更改
请求选项(重新编译)
参数化计划已刷新
测试计划线性化
影响数据库版本的计划已更改
查询存储计划强制策略已更改
查询存储计划强制失败
查询存储缺少计划
交错执行需要重新编译
不是重新编译
多计划语句需要编译替代查询计划