普通嫌犯:
- adhoc中的常量,代码中的参数
- 代码中的数据类型不匹配
- 参数嗅探
要点1:优化器可以为常数选择最佳方案。
更改常数=更改计划。参数化全包是可恢复的
由于数据类型优先级,第2点将引入隐式转换,
例如varchar列与nvarchar参数相比
第3点:使用参数屏蔽或优化未知
编辑:测试:运行存储的proc,运行sp_updatestats,然后再次运行。这将使缓存的计划无效,这比清除计划缓存更好
编辑:jcolebrand的评论后
您可以通过多种方式禁用嗅探。主要的三个是
- 推荐。这真是愚蠢的海事组织。
- 优化(原文如此)未知
- 参数屏蔽
参数屏蔽:
DECLARE @MaskedParam varchar(10)
SELECT @MaskedParam = @SignaureParam
SELECT...WHERE column = @MaskedParam
屏蔽和OPTIMIZE提示具有相同的效果(可能出于不同的原因)。也就是说,优化器必须使用统计信息和数据分布(请注意:仍由Mark Storey-Smith 进行 测试)根据自身的价值评估参数?,而不是他们最后一次拨打的电话。优化器可以重新编译或不重新编译。SQL Server 2005添加了语句级别的重新编译,因此影响较小
现在,为什么带有“嗅探”参数的计划与“蒙版” /“未知”参数相比是“粘性”的,我不确定。
从SQL Server 2000开始,除了最简单的代码,我都使用了参数屏蔽。我注意到,使用更复杂的代码很容易发生这种情况。在我的旧工作中,我有一些报告过程,可以更改计划参数的默认值。我认为,“货运崇拜”方法比支持电话要容易。
聊天后,编辑2,2011年10月12日
据我所知
,参数掩码和OPTIMIZE FOR UNKNOWN具有相同的效果。提示比掩码更干净,但它是在SQL Server 2008中添加的。
参数嗅探发生在编译时。
WITH RECOMPILE每次执行都会生成一个新计划。这意味着不良的默认选择会影响计划。在我的上一份工作中,我可以通过一些报告代码轻松地演示这一点:更改参数默认值会更改计划,而不管所提供的参数如何。
这篇MS Connect文章很有趣:存储过程中的次优索引用法(在下面的SO回答之一中提到)
- Bob Beauchemin也提到了
显着的问题
来自SO的链接:
WHERE
子句中引用变量?