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

Mic*_*ray 41 sql-server ssms sql-server-2008 query-performance arithabort

我正在尝试在我维护的Web应用程序中调试SQL超时的来源.我有C#代码的源代码,所以我确切地知道正在运行什么代码.我已经将应用程序调试到执行超时的SQL代码的行,并且我在SQL分析器中观察运行的查询.

当此查询从Web执行时,它会在30秒后超时.但是,当我完全按照Profiler中显示的方式剪切/粘贴查询时,我将其放入SSMS并运行它,它几乎立即返回.我已经跟踪了ARITHABORT在Web正在使用的连接中设置为OFF的问题(也就是说,如果我在SSMS会话中关闭ARITHABORT,它会运行很长时间,如果我将其重新打开,那么它会运行很快).但是,阅读ARITHABORT的描述,它似乎并不适用......我只做一个简单的SELECT,并且根本没有执行任何算法......只有一个带有WHERE条件的INNER JOIN:

为什么ARITHABORT OFF会在此上下文中导致此行为?有什么办法可以改变SSMS对该连接的ARITHABORT设置吗?我正在使用SQL Server 2008.

Aar*_*and 39

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

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

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

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

SET ARITHABORT ON; SELECT ...
Run Code Online (Sandbox Code Playgroud)

有关此问题发生原因的更多信息,请参阅Erland Sommarskog的精彩文章:

  • +1我有完全相同的事情.通过Web应用程序运行时超时,通过SMSS运行时<1秒.将SET ARITHABORT ON添加到sproc定义修复它.谢谢!PS到底是什么意思? (3认同)
  • @David - 只是要明确`ARITHABORT`本身不是原因,并且将"SET ARITHABORT ON"添加到存储的proc定义并不意味着问题不会再次发生.问题是参数嗅探. (3认同)
  • 我还尝试使用 DBCC FREEPROCCACHE 转储计划缓存,但这似乎没有任何效果 - 网络仍然很慢。当我将服务器上的 ARITHABORT 设置设置为 ON 后,问题就从网络上清除了。我实际上是在问如何通过 SSMS 连接影响其他连接的设置,但我认为这是不可能的。 (2认同)

Str*_*ior 12

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

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

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE
Run Code Online (Sandbox Code Playgroud)

更新

似乎大多数人最终很少发生这个问题,而上述技术是一个体面的一次性修复.但是,如果一个特定的查询显示出这一问题不止一次,更长远的解决这个问题是使用查询提示像OPTIMIZE FOROPTION(Recompile),如在 这篇文章.

  • 刷新整个过程缓存并不是一个很好的解决方案TBH它只是一个非常昂贵的短期修复.为什么你还在运行`DBCC DROPCLEANBUFFERS`?正确的做法是调查和修复参数嗅探问题,这意味着两个执行计划是不同的.见[http://www.sommarskog.se/query-plan-mysteries.html](http://www.sommarskog.se/query-plan-mysteries.html) (5认同)

Nov*_*NET 5

我以前多次遇到过这个问题,但是如果您有一个存在相同问题的存储过程,则删除并重新创建存储过程将解决该问题。

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

我知道这可能不是原始发帖者想要的,但可能会帮助遇到同样问题的人。

  • 这是一篇解释参数嗅探的好文章http://www.sommarskog.se/query-plan-mysteries.html#otherreasons (2认同)