C# 存储过程性能-这是野生的吗?
这个问题与其说是关于找到解决方案,不如说是关于如何解释我从SQL Server看到的BizBarry行为 我有一个具有以下签名的存储过程:C# 存储过程性能-这是野生的吗?,c#,sql-server-2008,stored-procedures,C#,Sql Server 2008,Stored Procedures,这个问题与其说是关于找到解决方案,不如说是关于如何解释我从SQL Server看到的BizBarry行为 我有一个具有以下签名的存储过程: alter procedure MySP @param1 uniqueidentifier, @param2 uniqueidentifier, @param3 uniqueidentifier 给定一组特定的参数,从C#(使用SqlCommand.ExecuteRea
alter procedure MySP @param1 uniqueidentifier,
@param2 uniqueidentifier,
@param3 uniqueidentifier
给定一组特定的参数,从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
然后,在SP的其余部分中,我们用本地副本替换对输入参数的所有引用
瞧。SP在2秒内执行。而这里的团队则目瞪口呆
女士们先生们,有人能解释一下这种行为吗 这听起来像
根据微软的定义:
“参数嗅探”是指SQL Server的执行环境在编译或重新编译期间“嗅探”当前参数值,并将其传递给查询优化器的过程,以便使用它们生成可能更快的查询执行计划。单词“current”指的是语句调用中出现的导致编译或重新编译的参数值
看起来你已经找到了一个解决方案,另一个是使用EXEC。。。重新编译时:
当执行具有非典型参数值的存储过程时,“EXEC…with RECOMPILE”可用于确保新查询计划不会替换使用典型参数值编译的现有缓存计划
我建议阅读Erland Sommarskog的优秀文章: 它有关于这个问题的全部细节
通常,缓存查询计划时,缓存键中会使用一些查询设置。默认SSMS设置中的这些设置与默认连接字符串中的设置不同,因此可能存在不同的查询计划。我有一个类似的情况,当时我有一个xml类型的参数,需要花费大量时间执行。我采用了同样的方法,创建了一个局部变量,并传入了参数值,它运行得非常快:)
SQL开始编译SP以创建其执行计划时,会考虑在其参数中传递的值以影响执行计划。但如果将参数值分配给局部变量,并在SP代码中使用该变量,则SQL不会考虑这些参数来影响执行计划,因此,您可以从查询中获得更快的响应。可能最好在此处使用与
参数不同的词,以避免与存储过程参数混淆。@MartinSmith-fair point。更改为设置
-你觉得怎么样?我觉得不错。这些可以在下面的DMO中找到:issys.dm_exec_plan_attributes
@Shaul-我建议看看他的其他文章。动态SQL也是一个破解工具。太棒了。我们无意中发现了教科书上的解决方案,却没有意识到!