从Web上调用存储过程很慢,快速从Management Studio调用

iam*_*ous 94 asp.net stored-procedures sql-server-2008

我有一个存储过程,每次从Web应用程序调用它都会疯狂地超时.

我启动了Sql Profiler并跟踪了那些超时的调用,最后找到了这些东西:

  1. 当从MS SQL Management Studio中执行语句时,使用相同的参数(实际上,我从sql profile trace复制了过程调用并运行它):它以5~6秒的平均值完成.
  2. 但是当从Web应用程序调用时,它需要超过30秒(在跟踪中),因此我的网页实际上超时了.

除此之外,我的web应用程序都有自己的用户事实上,每一件事情是相同的(相同的数据库,连接,服务器等),我也试过直接与Web应用程序的用户的工作室运行查询,并没有花费超过6秒.

我怎样才能知道发生了什么?

我假设它与我们使用BLL> DAL图层或表适配器这一事实无关,因为跟踪清楚地显示了延迟在实际过程中.这就是我所能想到的.

编辑我在这个链接中发现ADO.NET设置ARITHABORT为true - 这在大多数情况下是好的,但有时会发生这种情况,建议的解决方法是向with recompile存储过程添加选项.在我的情况下,它不起作用,但我怀疑它与此非常相似.任何人都知道ADO.NET做了什么或者我在哪里可以找到规范?

Str*_*ior 77

我过去曾遇到过类似的问题,所以我很想看到解决这个问题的方法.Aaron Bertrand对OP的评论导致Query从Web执行时超时,但是从SSMS执行时超级快,虽然问题不重复,但答案很可能适用于您的情况.

从本质上讲,它听起来像SQL Server可能有一个损坏的缓存执行计划.您正在使用您的Web服务器进行糟糕的计划,但SSMS会出现不同的计划,因为ARITHABORT标志上有不同的设置(否则会对您的特定查询/存储过程没有影响).

请参阅ADO.NET调用T-SQL存储过程导致另一个示例的SqlTimeoutException,具有更完整的解释和解决方案.

  • 嗨,清除缓存``DBCC DROPCLEANBUFFERS``和``DBCC FREEPROCCACHE``就可以了!我猜测执行计划有点腐败或没有更新.我怀疑这是一个永久性的修复,如果它可能一旦腐败,它可以再次做到.所以我仍在调查可能的原因.由于Web应用程序又重新开始工作,我不需要感受到压力.非常感谢. (44认同)
  • 而不是运行DBCC DROPCLEANBUFFERS和DBCC FREEPROCCACHE,它将清除所有执行计划,您可以删除并重新创建问题存储过程. (8认同)
  • @Mangist:因为这是一个复杂的问题,所以没有灵丹妙药,但你可以尝试在导致问题的查询中使用`OPTIMIZE FOR`或`OPTION(Recompile)`查询提示.[本文](http://sqlperformance.com/2013/08/t-sql-queries/parameter-sniffing-embedding-and-the-recompile-options)深入讨论了这个问题.如果实体框架正在生成您的查询,[this post](http://stackoverflow.com/a/26762756/120955)似乎提供了一种向查询添加查询提示的方法. (4认同)
  • @iamserious - 你钉了它谢谢!更改我的存储过程后,我遇到了超时问题.然后我运行了你上面提到的两个DBCC命令,它解决了这个问题. (2认同)
  • @iamserious:清除缓存也适合我.谢谢! (2认同)

Zan*_*ane 49

我还体验到,查询在网络上运行缓慢且在SSMS中运行速度很快,我最终发现问题是所谓的参数嗅探.

对我来说,修复是将sproc中使用的所有参数更改为局部变量.

例如.更改:

ALTER PROCEDURE [dbo].[sproc] 
    @param1 int,
AS
SELECT * FROM Table WHERE ID = @param1 
Run Code Online (Sandbox Code Playgroud)

至:

ALTER PROCEDURE [dbo].[sproc] 
    @param1 int,
AS
DECLARE @param1a int
SET @param1a = @param1
SELECT * FROM Table WHERE ID = @param1a
Run Code Online (Sandbox Code Playgroud)

看起来很奇怪,但它解决了我的问题.

  • 哇,我有同样的问题,并且不相信这会起作用,但确实如此. (3认同)
  • 可能是因为更改proc会导致创建新的执行计划,因此解决方案并不是真正将输入变量复制到局部变量,而只是强制生成新的执行计划(如接受的解决方案中所述)? (3认同)
  • 是的,这真的不是答案。您只需重新编译 sproc 即可获得相同的更改。您至少应该运行它一周并确保它确实已修复。 (2认同)

Cli*_*int 7

不是垃圾邮件,但作为其他人的希望有用的解决方案,我们的系统看到了高度的超时.

我尝试使用设置存储过程进行重新编译sp_recompile,这解决了一个SP的问题.

最终有更多的SP超时,其中许多以前从未这样做,通过使用DBCC DROPCLEANBUFFERS并且DBBC FREEPROCCACHE事故发生率明显下降 - 仍然存在孤立事件,有些地方我怀疑计划重建正在进行一段时间,以及一些SP真正表现不佳并且需要重新评估的地方.


Tun*_*dey 5

可能是在 Web 应用程序调用 SP 之前进行的其他一些数据库调用使事务保持打开状态?这可能是此 SP 在 Web 应用程序调用时等待的原因。我说隔离 Web 应用程序中的调用(将其放在新页面上)以确保 Web 应用程序中的某些先前操作导致此问题。