我想知道你们是否可以帮我解决我最近在SQL Server上遇到的一个奇怪问题。
我有一个存储过程(让我们调用SPold
)这是一个相当大的存储过程(在应用程序中不可能这样做,因为大约6000个用户的信息需要单独返回(我根据Surname将其减少到1000))。存储过程通常在几秒钟内执行,并且每隔几分钟调用一次。
今天早上,存储过程突然执行了4-10倍,导致了一些超时。我发现通过使用新名称(SPnew
)复制程序并执行,我会再次获得快速执行时间。这向我表明执行计划是原始的SPold
的问题,所以我决定通过重新编译来执行它。这会更快地返回结果(尽管不如SPnew
快),但用户对SPold
的后续调用再次变慢。这就好像没有保留新的计划。
我所做的就是解决此问题,将Exec SPnew
放入SPold
,现在对SPold
的调用再次快速返回。
有谁知道这里发生了什么?隔夜更新的唯一事情是统计数据,但我认为这会影响SPold
和SPnew
。
答案 0 :(得分:5)
由于参数嗅探,听起来您遇到了错误缓存的查询计划。
你可以发布存储过程吗?
在SQL Server 2005中,您可以使用OPTIMIZE FOR查询提示来获取参数的首选值,以解决与参数嗅探相关的一些问题:
OPTIMIZE FOR 指示查询优化器为本地使用特定值 编译和优化查询时的变量。使用该值 仅在查询优化期间,而不是在查询执行期间。 OPTIMIZE FOR可以抵消参数检测行为 优化程序或可在创建计划指南时使用。更多 信息,请参阅Recompiling Stored Procedures和Optimizing Queries in Deployed Applications by Using Plan Guides。
虽然SQL Server 2005不支持OPTIMIZE FOR UNKNOWN(在SQL Server 2008中引入) 将消除给定参数的参数嗅探:
OPTION (OPTIMIZE FOR (@myParam UNKNOWN))
通过将参数复制到局部变量,然后在查询中使用局部变量,可以在SQL Server 2005中实现相同的效果。
答案 1 :(得分:4)
我也遇到过Sql Server 2005的两个“奇怪”案例,这也可能与你的问题有关。
在第一种情况下,我的程序在以dbo运行时快速执行,并且在从应用程序运行时在另一个用户帐户下运行缓慢。
在第二种情况下,程序的查询计划针对首次调用过程的参数值进行了优化,然后该计划也被重用于其他参数值,导致执行缓慢。
对于第二种情况,解决方案是将参数值复制到过程中的局部变量中,然后使用查询中的变量而不是参数。