所以今天早上我们有一个长时间运行的 proc 导致问题(30 秒 + 运行时间)。我们决定检查参数嗅探是否是罪魁祸首。因此,我们重写了 proc 并将传入的参数设置为变量,以阻止参数嗅探。一种尝试过的/真实的方法。Bam,查询时间得到改善(不到 1 秒)。在查看查询计划时,在原始未使用的索引中发现了改进。
为了验证我们没有得到误报,我们对原始 proc 进行了 dbcc freeproccache 并重新运行以查看改进的结果是否相同。但是,令我们惊讶的是,原来的 proc 仍然运行缓慢。我们再次尝试使用 WITH RECOMPILE,但仍然很慢(我们尝试在对 proc 的调用以及在 proc 内部进行重新编译)。我们甚至重新启动了服务器(显然是开发箱)。
所以,我的问题是……当我们在空计划缓存上得到相同的慢查询时,参数嗅探怎么会受到指责……不应该有任何参数嗅探???
我们是否会受到与计划缓存无关的表统计信息的影响。如果是这样,为什么将传入参数设置为变量会有所帮助??
在进一步的测试中,我们还发现,将在PROC的内部的OPTION(OPTIMIZE未知)DID得到预期的改进计划。
所以,你们中的一些人比我更聪明,你能提供一些关于幕后发生了什么来产生这种结果的线索吗?
另一方面,慢计划也有理由提前中止,GoodEnoughPlanFound
而快计划在实际计划中没有提前中止原因。
总之
更新:
在此处查看慢速执行计划:https : //www.dropbox.com/s/cmx2lrsea8q8mr6/plan_slow.xml
在此处查看快速执行计划:https : //www.dropbox.com/s/b28x6a01w7dxsed/plan_fast.xml
注意:出于安全原因,表、架构、对象名称已更改。
我有一个删除语句,它在存储过程中运行时使用了一个错误的计划,但在临时运行时选择了一个更好的计划。
我已经为查询使用的表重建了所有索引并删除了所有缓存。优化器仍然为存储过程选择了错误的计划。
我想知道为什么优化器对存储过程使用不同的执行计划而不是临时 SQL。
更新:我想它毕竟一定是参数 - 当我运行带有硬编码变量的临时代码时,我可以获得具有正确值的“坏”计划(它是一个日期,值是一岁似乎产生了“好”的计划)。现在尝试通过使用查询提示在 proc 上强制执行“好”计划。
解决方案:我最终通过使用 OPTIMIZE FOR UNKNOWN 提示获得了我想要的计划。