存储过程性能 - 这是WILD?

Sha*_*ica 5 c# stored-procedures sql-server-2008

这个问题并不是要找到一个解决方案,而是要解释我从SQL Server中看到过的奇怪行为.

我有一个带有以下签名的存储过程:

alter procedure MySP @param1 uniqueidentifier, 
                     @param2 uniqueidentifier, 
                     @param3 uniqueidentifier
Run Code Online (Sandbox Code Playgroud)

给定一组参数,这个过程需要很长时间才能从C#(使用SqlCommand.ExecuteReader())运行 - 大约2分钟.在直接查询会话中使用相同的参数,SP在2秒内运行.

花了很长时间,我甚至不会试图解释我们如何偶然发现这个解决方案,但这就是我们所做的:

在SP的开头,我们声明了3个局部变量并将它们分配给参数的值,如下所示:

declare @param1_copy uniqueidentifier, 
        @param2_copy uniqueidentifier, 
        @param3_copy uniqueidentifier

select @param1_copy = @param1,
       @param2_copy = @param2,
       @param3_copy = @param3
Run Code Online (Sandbox Code Playgroud)

然后,在SP的其余部分,我们用本地副本替换对输入参数的所有引用.

瞧.SP在2秒内执行.这里的团队非常棒.

现在,女士们,先生们,任何人都可以解释这种行为吗?

Luk*_*vin 8

这听起来像参数嗅探.

来自微软的定义:

"参数嗅探"是指SQL Server的执行环境在编译或重新编译期间"嗅探"当前参数值并将其传递给查询优化器的过程,以便它们可用于生成可能更快的查询执行计划."current"一词是指语句调用中出现的引起编译或重新编译的参数值.

看起来你已经找到了一个修复,另一个是使用EXEC ... WITH RECOMPILE:

在执行具有非典型参数值的存储过程时,可以使用"EXEC ... WITH RECOMPILE"来确保新查询计划不会替换使用典型参数值编译的现有缓存计划.