【问题标题】:SQL Server procedure timing outSQL Server 过程超时
【发布时间】:2012-07-04 11:49:34
【问题描述】:

从生产站点上的 ASP.NET 前端环境调用此存储过程时,我遇到了中间超时。它返回以下 sql 异常:

异常详细信息:System.Data.SqlClient.SqlException:超时 已到期。在完成之前超时时间已过 操作或服务器没有响应。

有趣的是,在服务器上或使用 Management Studio 从远程 PC 执行此过程时,它会在 6 秒内执行。但是,有时从 ASP.NET 应用程序执行时会超时?这个查询可以改进吗?还是这个问题与其他问题有关?有谁能帮忙吗?我已经阅读了一些关于在我的 web.config 中增加超时和启用连接字符串池的线程,但还没有尝试过。

 ALTER PROCEDURE [dbo].[Report_Activity]
    (
        @StartDate      DATETIME
    ,   @EndDate        DATETIME
    ,   @TotalActions INT OUTPUT
    )

    AS
    BEGIN 

        SELECT      @TotalActions = COUNT(EventHistoryId)
        FROM        dbo.SessionEventHistory
        WHERE       DateCreated BETWEEN @StartDate AND @EndDate

        SELECT      EventDescription, COUNT(EventHistoryId) AS EventCount           
        FROM        dbo.SessionEventHistory
        WHERE       DateCreated BETWEEN @StartDate AND @EndDate
        GROUP BY    EventDescription
        ORDER BY    EventDescription

SQL 架构:

CREATE TABLE [dbo].[SessionEventHistory](
    [EventHistoryID] [int] IDENTITY(1,1) NOT NULL,
    [SessionHistoryID] [int] NOT NULL,
    [CategoryID] [int] NULL,
    [UserName] [nvarchar](50) NULL,
    [IPAddress] [nvarchar](20) NOT NULL,
    [EventDescription] [nvarchar](1000) NOT NULL,
    [EventData] [varbinary](max) NULL,
    [DateCreated] [datetime] NOT NULL,
 CONSTRAINT [PK_UserEventHistory] PRIMARY KEY CLUSTERED 
(
    [EventHistoryID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[SessionEventHistory] ADD  CONSTRAINT [DF_UserEventHistory_DateCreated]  DEFAULT (getdate()) FOR [DateCreated]
GO

表有 3 个索引:

/****** Object:  Index [IX_SessionEventHistory_SessionHistoryId_CategoryId]    Script Date: 07/04/2012 10:47:06 ******/
CREATE NONCLUSTERED INDEX [IX_SessionEventHistory_SessionHistoryId_CategoryId] ON [dbo].[SessionEventHistory] 
(
    [SessionHistoryID] ASC,
    [CategoryID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO


/****** Object:  Index [IX_SessionEventHistory_UserName_DateCreated]    Script Date: 07/04/2012 10:47:09 ******/
CREATE NONCLUSTERED INDEX [IX_SessionEventHistory_UserName_DateCreated] ON [dbo].[SessionEventHistory] 
(
    [UserName] ASC,
    [DateCreated] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO


/****** Object:  Index [PK_UserEventHistory]    Script Date: 07/04/2012 10:47:14 ******/
ALTER TABLE [dbo].[SessionEventHistory] ADD  CONSTRAINT [PK_UserEventHistory] PRIMARY KEY CLUSTERED 
(
    [EventHistoryID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

编辑

我添加了以下索引,看起来还可以吗?

CREATE NONCLUSTERED INDEX [IX_SessionEventHistory_DateCreated] ON [dbo].[SessionEventHistory] 
(
    [DateCreated] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

【问题讨论】:

  • 在 [DateCreated] 上放置索引可能会有所帮助
  • @DJ 我同意,该索引可能有助于提高整体效率,但如果具有相同参数的相同查询在不同应用程序中表现不同,那么它可能不止于此。
  • DateCreated (IX_SessionEventHistory_UserName_DateCreated) 上已有索引?
  • @FaNIX 但该索引没有 DateCreated 作为前导列。因此,除非查询还包含一个 where 子句或包含 UserName 列的组,否则您应该在执行计划中看到该索引不用于帮助满足此查询。
  • 可能是参数嗅探 - 尝试使用本地日期变量 - 还要查看 Aaron 在下面发布的优秀链接...

标签: sql-server tsql query-optimization ssms connection-timeout


【解决方案1】:

查看您的 ASP.Net 应用程序和 SSMS 会话的 sys.dm_exec_sessions。我会冒险猜测您的SET 设置中至少有一个是不同的。这可能会促成不同的计划(最终这归因于参数嗅探),并且应用程序端通常会因此而变得更糟。

有关更多详细信息,请参阅这些其他问题:

Stored procedure slow when called from web, fast from Management Studio

Procedure times out from ADO.NET but not in SSMS

Query times out when executed from web, but super-fast when executed from SSMS

ADO .NET vs. SQL Server Management Studio - ADO performs worse

另请阅读this great article by Erland Sommarskog

【讨论】:

  • 问题不在于查询,尽管可以稍微优化一下。问题出在 SQLDBCommand.CommandTimeout 上。默认情况下是 30 秒,我的程序没有 WITH (NOLOCK),所以当多个用户请求报告时,它会大大减慢,然后超过 30 秒,然后繁荣,DBCommand 以 SqlTimeout 异常关闭。通过增加 .CommandTimeout=90,并引入 WITH (NOLOCK),解决了问题:)
  • 好吧,我真的不会把这两件事都称为修复,但很高兴你在上面贴了创可贴。 :-)
【解决方案2】:

也许这是用一些非典型的 SP 调用创建的糟糕的执行计划。 尝试在执行 SP 时或在定义中使用 WITH RECOMPILE

EXEC [dbo].[Report_Activity] @StartDate, @EndDate, @TotalActions WITH RECOMPILE

ALTER PROCEDURE [dbo].[Report_Activity]
    (
        @StartDate      DATETIME
    ,   @EndDate        DATETIME
    ,   @TotalActions INT OUTPUT
    )
WITH RECOMPILE
AS
...

您也可以运行sp_recompile 来标记您的SP,以便在下次执行时重新编译。

【讨论】:

    猜你喜欢
    • 2012-04-27
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 2018-06-19
    • 2011-05-01
    • 2012-02-29
    相关资源
    最近更新 更多