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 次执行会持续一段时间。
问题:为什么我最常用的查询会转储表单缓存,我该如何阻止它发生?
语句可能被重新编译的原因有很多,包括性能和正确性相关的原因。
例如,查询使用的索引可能已被删除,在这种情况下,必须重新编译计划,因为它确实无法在该状态下运行。
或者统计信息可能已经更新到足以进行自动重新编译。
根据服务器上的负载,以及此语句真正重新编译的频率,您可能能够使用此扩展事件会话捕获实际原因:
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)
| 地图值 |
|---|
| 架构已更改 |
| 统计数据已更改 |
| 延迟编译 |
| 设置选项更改 |
| 临时表已更改 |
| 远程行集已更改 |
| 对于已更改的浏览权限 |
| 查询通知环境已更改 |
| 分区视图已更改 |
| 光标选项已更改 |
| 请求选项(重新编译) |
| 参数化计划已刷新 |
| 测试计划线性化 |
| 影响数据库版本的计划已更改 |
| 查询存储计划强制策略已更改 |
| 查询存储计划强制失败 |
| 查询存储缺少计划 |
| 交错执行需要重新编译 |
| 不是重新编译 |
| 多计划语句需要编译替代查询计划 |
| 归档时间: |
|
| 查看次数: |
381 次 |
| 最近记录: |