查询计划突然重新编译并降低了性能

时间:2019-03-06 02:12:14

标签: sql sql-server sql-server-2008 sql-execution-plan query-planner

场景:我们有一个简单的选择查询

Declare P@

SELECT TOP(1) USERID
FROM table
WHERE non_clusteredindex_column = (@P) ORDER BY PK_column DESC

自1年以来,通常执行时间为0.12秒。但是昨天昨天恰好在午夜之后,它开始消耗我所有的CPU并花了150秒来执行。我检查了SP_who2,发现没有死锁,除了这一查询消耗了所有CPU外,什么也没有。我决定重新启动服务器,以消除任何参数嗅探问题或杀死任何陈旧的连接。在重新启动服务器进行以后的根本原因分析之前,我进行了1分钟的SLQ事件探查器跟踪。重新启动后,一切恢复正常。我很惊讶,好奇地开始查看我所使用的探查器中的执行计划,并将其与SAME查询的当前执行计划进行比较。我发现两者是不同的。

有问题的Night之前的执行计划与Reboot之后的执行计划相同。 (做完美的索引搜索

但是问题夜间SQL探查器中的执行计划正在执行全索引扫描,这将占用所有CPU并花费150秒的时间来执行。

问题

我可以说执行计划突然重新编译,或者在昨天午夜之后重新启动执行查询(使用全扫描),然后重新启动后,它又开始使用旧的良好执行计划(索引SEEK)。

第一季度。是什么使SQL Server突然使用新的EXECUTION计划? 第二季度。重新启动后,是什么使SQL Server使用旧的良好执行计划? 第三季度。我传递参数时与参数嗅探有关的任何事情。但是从技术上讲,它不应该是因为“参数”列的结构井井有条,而且数据分布均匀。

2 个答案:

答案 0 :(得分:0)

听起来您有参数嗅探问题。我看不到您的数据,但是即使在简单的查询场景中,当许多行与参数结果匹配时,即使在不正确​​的情况下,数据也会翻转到扫描,或者数据存在其他问题,例如,许多值是唯一的,但是在某些情况下,他们决定在表的很大一部分中列应为0,从而将所有内容都抛出循环。如果来自代码的查询运行缓慢,但是您可以通过ssms执行测试过程执行,则这是一个很大的危险信号,这是您的问题所在。

您是正确的,SQL重新启动会刷新所有计划缓存,或者您可以手动刷新所有计划,但是您绝对不希望使用此方法来修复单个过程的计划。一个快速的解决方法是可以执行EXEC sp_recompile'dbo.procname';强制其仅刷新一个过程执行计划并制定一个新的计划。重做所有计划(尤其是在繁忙的数据库中)可能会导致其他进程严重关注性能,并且重新启动当然会导致一些停机时间。尽管如果您已经确定了导致问​​题的参数,但是这只会暂时解决问题,尽管我会考虑考虑针对未知提示进行优化,专门针对已发现的参数嗅探问题而设计。但也可能要确保在您的环境中定期进行一些良好的索引维护,以防引起不良计划而不是sql引擎。

答案 1 :(得分:0)

根据您的情况,您可以执行以下操作:

-在数据库设置中激活查询存储选项。将操作模式设置为开。

enter image description here

-这将开始捕获每个请求的查询计划。

-您可以开始跟踪消耗大量资源的查询

-最后,您可以强制执行计划用于该查询

enter image description here