msg*_*sme 9 sql-server execution-plan
我有一个删除语句,它在存储过程中运行时使用了一个错误的计划,但在临时运行时选择了一个更好的计划。
我已经为查询使用的表重建了所有索引并删除了所有缓存。优化器仍然为存储过程选择了错误的计划。
我想知道为什么优化器对存储过程使用不同的执行计划而不是临时 SQL。
更新:我想它毕竟一定是参数 - 当我运行带有硬编码变量的临时代码时,我可以获得具有正确值的“坏”计划(它是一个日期,值是一岁似乎产生了“好”的计划)。现在尝试通过使用查询提示在 proc 上强制执行“好”计划。
解决方案:我最终通过使用 OPTIMIZE FOR UNKNOWN 提示获得了我想要的计划。
普通嫌犯:
第 1 点:优化器可以为常量选择最佳方案。
改变常数 = 改变计划。参数化的plen是可重用的
由于数据类型优先级,第 2 点将引入隐式转换,
例如与 nvarchar 参数相比的 varchar 列
第 3 点:使用参数屏蔽或 OPTIMIZE FOR UNKNOWN
编辑:要测试:运行存储过程,运行 sp_updatestats,再次运行。这将使缓存的计划无效,这比清除计划缓存更好
编辑:在 jcolebrand 的评论之后
您可以通过多种方式禁用嗅探。主要的3个是
参数屏蔽:
DECLARE @MaskedParam varchar(10)
SELECT @MaskedParam = @SignaureParam
SELECT...WHERE column = @MaskedParam
Run Code Online (Sandbox Code Playgroud)
屏蔽和 OPTIMIZE 提示具有相同的效果(可能出于不同的原因)。也就是说,优化器必须使用统计数据和数据分布(注意:仍在由 Mark Storey-Smith 测试)根据自己的优点评估参数? ,而不是他们上次调用的。优化器可以重新编译或不重新编译。SQL Server 2005 添加了语句级重新编译,因此影响较小
现在,与屏蔽/“未知”参数相比,为什么带有“嗅探”参数的计划是“粘性”的,我不确定。
除了最简单的代码,我从 SQL Server 2000 开始使用参数掩码。我已经注意到,更复杂的代码可能会发生这种情况。在我的旧工作中,我有一些报告过程,我可以更改计划参数默认值。我认为“货物崇拜”方法比支持电话更容易。
编辑 2, 12 Oct 2011, 经过一些聊天
据我所知
,参数屏蔽和 OPTIMIZE FOR UNKNOWN 具有相同的效果提示比屏蔽更清晰,但它是在 SQL Server 2008 中添加的。
参数嗅探发生在编译时。
WITH RECOMPILE 每次执行都会生成一个新计划。这意味着默认值选择不当会影响计划。在我的上一份工作中,我可以使用一些报告代码轻松演示这一点:无论提供的参数如何,更改参数默认值都会改变计划。
这篇 MS Connect 文章很有趣:存储过程中的次优索引使用(在下面的 SO 答案之一中提到)
显着的问题
嗅探是否仍然适用于 WITH RECOMPILE?也就是说,如果优化器知道要丢弃该计划,它是否旨在重用?
为什么嗅探计划是“粘性的”?
来自 SO 的链接:
归档时间: |
|
查看次数: |
1568 次 |
最近记录: |