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


97

我存储的过程在每次从Web应用程序中调用时都会疯狂地超时。

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

  1. 在MS SQL Management Studio中使用相同的参数执行语句时(实际上,我从sql概要文件跟踪复制了过程调用并运行了它):平均在5到6秒内完成。
  2. 但是,当从Web应用程序调用时,它花费了超过30秒的时间(在跟踪中),因此我的网页到那时实际上已超时。

除了我的Web应用程序有其自己的用户外,每件事都是相同的(相同的数据库,连接,服务器等),我还尝试了直接在Studio中与该Web应用程序的用户一起运行查询,并且该查询不超过6个秒

我如何找出正在发生的事情?

我认为这与我们使用BLL> DAL层或表适配器这一事实无关,因为该迹线清楚地表明延迟是在实际过程中进行的。这就是我能想到的。

我在此链接中发现EDIT,ADO.NET设置ARITHABORT为true-在大多数情况下都很好,但有时会发生这种情况,建议的解决方法是将with recompile选项添加到存储的proc中。就我而言,它不起作用,但我怀疑它与此非常相似。有谁知道ADO.NET还有什么功能,或者在哪里可以找到该规范?


1
这可能与返回多少数据有关?
巴里·凯

@Barry:不,因为我在Management Studio中运行相同的过程(也从跟踪中复制-表示相同的参数),所以它在6秒钟内运行。
iamserious 2011年

@Jayantha:并不是说sp的速度很慢,而是ado.net和sql之间有些关系。我看不到sp会有什么不同。
iareserious 2011年

2
SP是否返回大量数据,例如image / text / varchar(max)列?客户端要消耗的数据量将是巨大的,这将花费大量时间。SSMS可以更有效地切断这些结果集。
蒂姆·施密特

Answers:


79

过去我也遇到过类似的问题,所以我很想看到这个问题的解决方案。亚伦·贝特朗(Aaron Bertrand)对OP的评论导致从Web执行时查询超时,但从SSMS执行时查询速度超快,尽管问题不是重复,但答案很可能适用于您的情况。

从本质上讲,听起来SQL Server可能具有损坏的缓存执行计划。您正在用Web服务器达到糟糕的计划,但是SSMS却采用了另一种计划,因为ARITHABORT标志的设置不同(否则对您的特定查询/存储过程没有影响)。

有关另一个示例,请参见ADO.NET调用T-SQL存储过程会导致SqlTimeoutException的问题,并提供更完整的说明和解决方法。


这些是一些有趣的线索,将阅读更多有关它们的信息,然后再回馈..谢谢。
iamserious

44
嗨,清除缓存DBCC DROPCLEANBUFFERSDBCC FREEPROCCACHE做的伎俩!我猜测执行计划某种程度上已损坏或未更新。我怀疑这是一个永久性的解决方法,如果它一旦损坏就可以再次执行。因此,我仍在寻找合理的原因。由于该网络应用重新恢复工作,因此我无需感到压力。非常感谢。
2011年

2
@iamserious-您将其钉牢了,谢谢!更改存储过程后,我遇到了超时问题。然后,我运行了您上面提到的两个DBCC命令,它解决了该问题。
Induster,2012年

5
@Mangist:因为这是一个复杂的问题,所以没有灵丹妙药,但是您可以尝试在引起问题的查询中使用OPTIMIZE FOROPTION(Recompile)查询提示。本文深入讨论了该问题。如果Entity Framework正在生成您的查询,则该帖子似乎提供了一种向查询中添加查询提示的方法。
StriplingWarrior 2015年

8
您可以删除并重新创建问题存储过程,而不必运行将清除所有执行计划的DBCC DROPCLEANBUFFERS和DBCC FREEPROCCACHE。
jnoreiga 2015年

50

我还体验到查询在Web上运行缓慢,在SSMS中运行很快,最终我发现问题出在参数嗅探上。

对我来说,解决方法是将存储过程中使用的所有参数更改为局部变量。

例如。更改:

ALTER PROCEDURE [dbo].[sproc] 
    @param1 int,
AS
SELECT * FROM Table WHERE ID = @param1 

至:

ALTER PROCEDURE [dbo].[sproc] 
    @param1 int,
AS
DECLARE @param1a int
SET @param1a = @param1
SELECT * FROM Table WHERE ID = @param1a

似乎很奇怪,但是它解决了我的问题。


3
哇,我遇到了同样的问题,但我不相信这会起作用,但确实可以。
Lac Ho

1
Zane,您知道这是否可以永久解决问题,还是可以解决?谢谢!
Lac Ho

1
自进行此更改以来,我对存储过程的速度没有任何问题。
Zane 2013年

1
哇,它也解决了我的问题!这必须是sql server中的错误。当MSSQL可以在内部转换为本地功能以获得巨大性能时,为什么要迫使SQL编写者跳过这个愚蠢的圈呢?
HerrimanCoder

3
可能是因为更改proc会导致创建新的执行计划,所以解决方案不是真正将输入变量复制到局部变量,而只是强制生成新的执行计划(如已接受的解决方案所述)?
加兰·教皇

10

不是垃圾邮件,而是作为对其他人有用的解决方案,我们的系统看到了很大程度的超时。

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

最终,有SP的那名计时出,很多从来没有这样做之前,通过使用更大数量DBCC DROPCLEANBUFFERSDBBC FREEPROCCACHE超时的发生率也显著一落千丈-仍有孤立事件,有些地方我怀疑这个计划再生回吐一段时间,还有一些SP确实表现不佳,需要重新评估。


1
谢谢你 当使用时,使用sp_recompile命令标记用于重新编译的过程对我有用,DBCC DROPCLEANBUFFERS并且DBCC FREEPROCCACHE没有区别。
史蒂夫

4

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


1
@Tundey,您好,我隔离了通话,仍然需要大约30秒,并且超时。我想这一定是沟通之间的东西吗?
iamserious 2011年

1

只需重新编译存储过程(在我的情况下为表函数)就对我有用


1

就像@Zane所说的,这可能是由于参数嗅探。我经历了相同的行为,并查看了该过程的执行计划以及该sp的所有语句在一行中的内容(将所有语句复制到该过程中,将参数声明为变量,并将变量的值赋为参数有)。但是执行计划看起来完全不同。sp执行耗时3-4秒,并且立即返回一行具有完全相同值的语句。

执行计划

经过一番谷歌搜索后,我发现了有关该行为的有趣读物:应用程序中的速度慢,SSMS中的速度快?

在编译过程时,SQL Server不知道@fromdate的值会发生变化,但是在@fromdate的值为NULL的前提下编译过程。由于所有使用NULL的比较都会产生UNKNOWN,因此如果@fromdate在运行时仍具有该值,则查询根本无法返回任何行。如果SQL Server将输入值作为最终事实,则可以仅使用一个常量扫描构造一个根本不访问该表的计划(运行查询SELECT * FROM Orders WHERE OrderDate> NULL来查看此示例)。 。但是SQL Server必须生成一个计划,无论运行时@fromdate具有什么值,该计划都将返回正确的结果。另一方面,没有义务制定最适合所有价值的计划。因此,由于假定不返回任何行,因此SQL Server会选择“索引查找”。

问题是我有可以保留为null的参数,如果将它们作为null传递,则将使用默认值进行初始化。

create procedure dbo.procedure
    @dateTo datetime = null
begin
    if (@dateTo is null)
    begin
        select @dateTo  = GETUTCDATE()
    end

    select foo
    from dbo.table
    where createdDate < @dateTo
end

我将其更改为

create procedure dbo.procedure
    @dateTo datetime = null
begin
    declare @to datetime = coalesce(@dateTo, getutcdate())

    select foo
    from dbo.table
    where createdDate < @to
end 

它再次像魅力一样工作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.