我正在尝试调试我维护的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。
答案 0 :(得分:38)
所以你的C#代码正在使用什么方法向SQL Server发送一个临时SQL查询?您考虑过使用存储过程吗?这可能会确保相同的性能(至少在引擎中),无论谁调用它。
为什么呢? ARITHABORT设置是优化程序在确定如何执行查询(更具体地说,用于计划匹配)时查看的内容之一。缓存中的计划可能与SSMS具有相同的设置,因此它使用缓存的计划,但是使用相反的设置,您的C#代码正在强制重新编译(或者您可能正在使用 BAD 计划在缓存中),这在很多情况下肯定会损害性能。
如果您已经在调用存储过程(虽然我认为您没有发布查询,但是您可以尝试将OPTION(RECOMPILE)添加到存储过程中的违规查询(或查询)中。这将意味着这些语句将始终重新编译,但它可能会阻止使用您似乎遇到的错误计划。另一个选择是确保在编译存储过程时,使用SET ARITHABORT ON执行批处理。
最后,您似乎在询问如何更改SSMS中的ARITHABORT设置。我想您要问的是如何在代码中强制使用ARITHABORT设置。如果您决定继续从C#应用程序发送临时SQL,那么当然您可以发送一个命令作为具有由分号分隔的多个语句的文本,例如:
SET ARITHABORT ON; SELECT ...
有关此问题发生原因的详细信息,请参阅Erland Sommarskog的精彩文章:
答案 1 :(得分:12)
This answer包含解决此问题的方法:
通过在数据库上以管理员身份运行以下命令,无论ARITHABORT设置如何,所有查询都按预期运行。
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
似乎大多数人最终很少发生此问题,而上述技术是一次体面的修复。但是,如果某个特定查询不止一次出现此问题,则针对此问题的更长期解决方案是使用OPTIMIZE FOR
和OPTION(Recompile)
等查询提示,如this article中所述。< / p>
答案 2 :(得分:3)
我以前曾经多次遇到过这个问题,但是如果你有一个存储过程有同样的问题掉线并重新创建存储过程将解决问题。
这叫做参数嗅探。 您需要始终本地化存储过程中的参数,以避免将来出现此问题。
我知道这可能不是原始海报想要的,但也可能帮助有同样问题的人。
答案 3 :(得分:1)
如果使用Entity Framework,则必须知道默认情况下,字符串值的查询参数作为nvarchar发送到数据库,如果要比较的数据库列的类型为varchar,则取决于您的排序规则,查询执行计划可能需要“ IMPLICIT CONVERSION”步骤,强制进行全面扫描。我可以通过查看“昂贵查询中的数据库监视”选项来确认它,该选项显示执行计划。
最后,本文对此行为进行了解释: https://www.sqlskills.com/blogs/jonathan/implicit-conversions-that-cause-index-scans/
答案 4 :(得分:1)
仅使用ARITHABORT并不能解决问题,尤其是在使用参数化存储过程的情况下。
因为参数化存储过程可能导致使用缓存的查询计划的“参数嗅探”
因此,在得出结论之前,请检查以下链接。
the-elephant-and-the-mouse-or-parameter-sniffing-in-sql-server
答案 5 :(得分:0)
我有同样的问题,并通过执行程序“WITH RECOMPILE”修复。您也可以尝试使用参数嗅探。我的问题与SQL缓存有关。
答案 6 :(得分:0)
如果您可以更改代码以修复参数嗅探优化未知提示是您的最佳选择。如果你不能改变你的代码,那么最好的选择就是exec sp_recompile'proc of proc',这将强制只有一个存储过程获得一个新的执行计划。删除和重新创建一个proc会产生类似的效果,但如果有人在你删除它时尝试执行proc,可能会导致错误。 DBCC FREEPROCCACHE会删除所有缓存的计划,这些计划可能会严重破坏您的系统,包括在繁重的交易生产环境中造成大量超时。设置arithabort不是问题的解决方案,但它是一个有用的工具,用于发现参数嗅探是否是问题。
答案 7 :(得分:0)
我尝试从SMSS调用SP时遇到同样的问题需要2秒,而从webapp(ASP.NET)调用它需要大约3分钟。
我已经尝试了所有建议的解决方案 for file in abc.csv*
do
mv "$file" "$file__20170330"
done
,sp_recompile
和DBCC FREEPROCCACHE
,但没有解决我的问题,但是当尝试参数嗅探它就可以解决问题,并且工作正常。