从Web执行时查询超时,但从SSMS执行时超快

我试图在我维护的Web应用程序中debuggingSQL超时的来源。 我有C#代码的源代码,所以我确切知道哪些代码正在运行。 我已经将应用程序debugging到了执行超时的SQL代码的那一行,然后我观察SQL查询器中运行的查询。

当这个查询从networking执行时,它在30秒后超时。 但是,当我完全按照Profiler中的描述剪切/粘贴查询,并将其放入SSMS并运行时,它几乎立即返回。 我已经跟踪到的问题是在networking连接中将ARITHABORT设置为OFF(也就是说,如果我在SSMS会话中closures了ARITHABORT,它会运行很长时间,如果我将它重新打开,非常快)。 然而,阅读ARITHABORT的描述,它似乎并不适用…我只做一个简单的SELECT,并没有执行任何算术..只是一个单一的内部联接与WHERE条件:

为什么在这种情况下,ARITHABORT OFF会导致这种行为? 有什么办法可以改变从SSMS的连接ARITHABORT设置? 我正在使用SQL Server 2008。

那么你的C#代码是使用什么方法向SQL Server发送临时SQL查询? 你有没有考虑过使用存储过程? 这可能会确保相同的性能(至less在引擎中),无论谁称它。

为什么? ARITHABORT设置是优化程序在确定如何执行查询(更具体地说,用于计划匹配)时要考虑的事情之一。 caching中的计划可能与SSMS具有相同的设置,因此它使用caching的计划,但是相反的设置,C#代码会强制重新编译(或者您正在执行caching中的BAD计划),在很多情况下肯定会伤害到性能。

如果您已经调用存储过程(您没有发布您的查询,但我认为您的意思是),则可以尝试将OPTION(RECOMPILE)添加到存储过程中的一个或多个查询中。 这将意味着这些语句将会重新编译,但是它可能会阻止您使用的错误计划。 另一个选项是确保在编译存储过程时,使用SET ARITHABORT ON执行批处理。

最后,你似乎在问如何改变SSMS中的ARITHABORT设置。 我想你要问的是如何强制代码中的ARITHABORT设置。 如果您决定继续从您的C#应用​​程序发送临时SQL,那么当然您可以发送一个命令作为具有多个由分号分隔的语句的文本,例如:

SET ARITHABORT ON; SELECT ... 

有关此问题发生的更多信息,请参阅Erland Sommarskog的伟大文章:

  • 在申请慢,在SSMS快速? 了解性能之谜

这个答案包括解决这个问题的方法:

通过在数据库上以pipe理员身份运行以下命令,无论ARITHABORT设置如何,所有查询均按预期方式运行。

  DBCC DROPCLEANBUFFERS DBCC FREEPROCCACHE 

更新

似乎大多数人最终会遇到这个问题的发生很less,而上述技术是一个体面的一次性修复。 但是如果一个特定的查询不止一次地出现这个问题,这个问题的一个更长期的解决scheme就是使用查询提示,如OPTIMIZE FOROPTION(Recompile) ,如本文所述 。

我以前有过这个问题很多次,但如果你有一个存储过程相同的问题,并删除和重新创build存储过程将解决这个问题。

这就是所谓的参数嗅探。 您需要始终本地化存储过程中的参数,以避免将来出现此问题。

我知道这可能不是原来的海报,但可能会帮助有同样问题的人。

我遇到了同样的问题,通过执行“WITH RECOMPILE”过程修复了这个问题。 您也可以尝试使用参数嗅探。 我的问题与SQLcaching有关。

如果你可以改变你的代码来修复参数嗅探优化未知的提示是你最好的select。 如果你不能改变你的代码,最好的select是exec sp_recompile'proc的名字',这将强制只有一个存储过程得到一个新的执行计划。 删除和重新创build一个proc将会产生类似的效果,但如果有人试图执行proc的时候可能会导致错误。 DBCC FREEPROCCACHE会丢弃所有可能破坏系统的caching计划,包括在繁重的事务生产环境中导致大量超时。 设置arithabort不是解决问题的办法,但是是一个有用的工具,用于发现参数嗅探是否是问题。

当我尝试从SMSS调用SP时,我遇到了同样的问题,它花了2秒,而从webapp(ASP.NET)花了大约3分钟。

我已经尝试了所有build议的解决schemesp_recompileDBCC FREEPROCCACHEDBCC DROPCLEANBUFFERS但没有解决我的问题,但是当尝试参数嗅探它做了伎俩,工作得很好。

Interesting Posts