这是我在另一个论坛上提出的一个问题,该问题得到了一些不错的答案,但我想知道这里是否有人有更多的见解.
问题是,当Web应用程序中的某个页面进入存储过程调用时会超时,因此您使用Sql Profiler或应用程序跟踪日志来查找查询并将其粘贴到管理工作室中我们为什么运行缓慢.但是你从那里开始运行它只是开始燃烧,每次返回不到一秒钟.
我的具体案例是使用ASP.NET 2.0和Sql Server 2005,但我认为这个问题可能适用于任何RDBMS系统.
这是我迄今为止从我的研究中学到的东西.
.NET发送的连接设置与登录管理工作室时的连接设置不同.如果你用Sql Profiler嗅探连接,你会看到以下内容:
-- network protocol: TCP/IP set quoted_identifier off set arithabort off set numeric_roundabort off set ansi_warnings on set ansi_padding on set ansi_nulls off set concat_null_yields_null on set cursor_close_on_commit off set implicit_transactions off set language us_english set dateformat mdy set datefirst 7 set transaction isolation level read committed
我现在在登录到sql server时运行的每个查询中粘贴那些设置,以确保设置相同.
对于这种情况,我在断开连接并重新连接后单独尝试了每个设置,并发现将arithabort从off更改为on将问题查询从90秒减少到1秒.
最可能的解释与参数嗅探有关,参数嗅探是一种Sql Server用来选择它认为最有效的查询计划的技术.当您更改其中一个连接设置时,查询优化器可能会选择不同的计划,在这种情况下,它显然选择了一个错误的计划.
但我并不完全相信这一点.我已经尝试在更改此设置后比较实际的查询计划,我还没有看到差异显示任何更改.
在某些情况下,arithabort设置还有其他可能导致查询运行缓慢的问题吗?
解决方案似乎很简单:只需将set arithabort置于存储过程的顶部即可.但这可能会导致相反的问题:更改查询参数并突然以"关闭"而不是"开启"运行得更快.
目前我正在运行"重新编译"程序,以确保每次都重新生成计划.对于这个特定的报告来说没关系,因为重新编译可能需要一秒钟,而且报告需要1-10秒才能返回(这是一个怪物).
但是,对于运行频率更高且需要尽快返回的其他查询,它不是一个选项,只需几毫秒.
我遇到过类似的问题.尝试在sproc create上设置"WITH RECOMPILE"选项,以强制系统在每次调用时重新计算执行计划.有时,查询处理器会在具有大量分支或案例语句的复杂存储过程中感到困惑,并且只会产生一个非常次优的执行计划.如果这似乎"修复"了问题,您可能需要验证统计信息是最新的和/或分解sproc.
您还可以通过分析sproc来确认这一点.当您从SQL Managment Studio执行它时,IO与从ASP.NET应用程序中分析它时的情况相比如何.如果他们非常多,那只会重新强制执行它会导致糟糕的执行计划.