我知道这与参数嗅探有关,但我只是对以下示例的某些内容感到困惑,即使是一项能够很好地完成这么多复杂事情的技术.
我们中的许多人遇到了间歇性运行比平时慢几个数量级的存储过程,然后如果从过程中复制出sql并在单独的查询窗口中使用相同的参数值,则它会像往常一样快速运行.
我刚刚修改了这样的程序:
alter procedure p_MyProc ( @param1 int ) as -- do a complex query with @param1
对此:
alter procedure p_MyProc ( @param1 int ) as declare @param1Copy int; set @param1Copy = @param1; -- Do the query using @param1Copy
它从跑步一分钟后回到不到一秒钟,就像它通常运行一样.这种行为似乎完全随机.对于10个@param1输入中的9个,查询速度很快,无论它最终需要处理多少数据,或者结果设置多大.但是对于那10个中的1个,它只是迷失了.修复是用查询中的相同int替换int?
这没有道理.
[编辑]
@gbn链接到这个问题,详细说明了类似的问题:
已知问题?:SQL Server 2005存储过程无法使用参数完成
我犹豫着哭"Bug!" 因为这经常是一个警察,但这对我来说确实看起来像个错误.当我使用相同的输入运行我的存储过程的两个版本时,我看到相同的查询计划.唯一的区别是原始版本需要运行超过一分钟,而带有goofy参数复制的版本会立即运行.
十分之一给出了缓存的错误计划.
RECOMPILE增加了开销,屏蔽允许根据它自己的优点(非常简单)评估每个参数.
通过错误的计划,如果10中的1对索引1产生扫描但是其他9对索引2产生搜索怎么办?例如,10分之一是50%的行?
编辑:其他问题
已知问题?:SQL Server 2005存储过程无法使用参数完成
存储过程对特定用户失败
编辑2:
重新编译不起作用,因为参数在编译时被嗅探.
来自其他链接(粘贴):
这篇文章解释了......
...parameter values are sniffed during compilation or recompilation...
最后(编辑3):
参数嗅探在当时可能是一个好主意,并且可能大部分都适用.我们全面地使用它来获取最终在WHERE子句中的任何参数.我们不需要使用它,因为我们知道只有少数(更复杂的例如报告或许多参数)可能导致问题,但我们使用它来保持一致性.
当用户抱怨并且我们应该使用掩蔽时,它会回来并咬我们的事实......