我正在尝试在维护的Web应用程序中调试SQL超时的源。我后面有C#代码的源代码,因此我确切知道正在运行的代码。我已经将应用程序调试到执行超时的SQL代码的那一行,然后观察在SQL事件探查器中运行的查询。

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

为什么在这种情况下ARITHABORT OFF会导致此行为?我可以通过SSMS更改该连接的ARITHABORT设置吗?我正在使用SQL Server 2008。

最佳答案

因此,您的C#代码使用哪种方法将临时SQL查询发送到SQL Server?您是否考虑过使用存储过程?无论是谁调用它,这都可能确保相同的性能(至少在引擎中)。

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

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

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

SET ARITHABORT ON; SELECT ...

有关为什么会发生此问题的更多信息,请参见Erland Sommarskog的精彩文章:
  • Slow in the Application, Fast in SSMS? Understanding Performance Mysteries
  • 10-06 10:11