【问题标题】:SQL Server stored procedure slows every executionSQL Server 存储过程会减慢每次执行的速度
【发布时间】:2012-02-04 14:51:19
【问题描述】:

我有一个存储过程,它使用一些游标进行许多选择和更新。

当我第一次执行该过程时,大约需要 30 秒。第二次执行大约需要 1 分钟。第三次大约 2 分钟。

每次执行都会减慢过程。现在大约需要 10 分钟。

出了什么问题?

变量:

declare @StatistikStatus nvarchar(100)
declare @SQL as nvarchar(MAX)
declare @Datum  as nvarchar(50) --Datum im nvarchar Format
declare @Datumdatetime datetime --Datum im datetime Format
declare @tickethistorieID as uniqueidentifier
declare @id int --ID der Terminauswertung. Wird bei Einträgen benötigt, die pro Ticket mehrere Termine vereinbart haben.
declare @nextTermin datetime --Wird bei Einträgen benötigt, die pro Ticket mehrere Termine vereinbart haben.
declare @status nvarchar(100)
declare @statusdiff as nvarchar(100)
declare @vorStatus as nvarchar(100)
declare @lastid as int
declare @tickethistoriemerker nvarchar(40)
declare @statistikstatusmerker nvarchar(100)
DECLARE @TicketID uniqueidentifier

示例光标:

DECLARE C_TicketHistorie CURSOR FOR
    SELECT  
        dbo.TicketHistorie.TicketID,dbo.TicketHistorie.Datum,dbo.tickethistorie.tickethistorieid
    FROM 
        dbo.TicketHistorie INNER JOIN
        dbo.Status ON dbo.TicketHistorie.NeueStatusID = dbo.Status.StatusID
        INNER JOIN dbo.StatuszuStatistikStatus as s on s.status_ID = dbo.Status.statusid
        INNER JOIN dbo.StatistikStatus as ss on s.bewertung_id = ss.id
    WHERE     
    ss.id = 5 AND -- 5 = HNR Terminbestätigung
        (dbo.Status.Name = N'Termin vereinbart') 
     AND ((YEAR(dbo.TicketHistorie.Datum) >= 2011 and day(dbo.TicketHistorie.Datum) >= 27 and month(dbo.TicketHistorie.Datum) >= 12)or YEAR(dbo.TicketHistorie.Datum) >= 2012)

    ORDER BY TicketID,Datum asc
OPEN C_TicketHistorie;

FETCH NEXT FROM C_TicketHistorie into @TicketID,@Datumdatetime,@TickethistorieID
WHILE @@FETCH_STATUS = 0
BEGIN
--some inserts etc.
FETCH NEXT FROM C_TicketHistorie into @TicketID,@Datumdatetime,@TickethistorieID
END
CLOSE C_TicketHistorie
DEALLOCATE C_TicketHistorie

我有 4 个光标。 还有一些像这样的动态SQL

SET @SQL ='UPDATE Statistik.dbo.terminauswertungab27122011 SET ['
                SET @SQL =@SQL + @StatistikStatus+']='''
                SET @SQL =@SQL + cast(@TicketHistorieID as NVARCHAR(36))+''''
                SET @SQL =@SQL + ' WHERE ID = ' + cast(@ID as nvarchar) +' and ['+@StatistikStatus+'] IS NULL' 
                EXEC (@SQL)

我使用 SSMS 调用该过程。

在 stp 的开头,我删除插入的表。然后我在做插入。每次执行的表行都相同

【问题讨论】:

  • 使用SSMS调用存储过程时是否会出现这种情况?还是仅当您从代码中调用它时?我们需要有关 proc 以及您如何使用它的更多详细信息。
  • 你需要提供更多细节,没有人能做的只是猜测。
  • 我想最可能的原因是您每次执行都会处理更多数据 - 您是否正在将数据复制/移动到显示(意外)增长的表中?可能不是您的过程执行得这么慢,而是您的数据库忙于分配更多空间。
  • iam 在 stp 的开头使用 SSMS 我删除了插入的表。然后我在做插入。每次执行时表行都相同
  • 我刚刚阅读了关于四个光标的部分。哇。关于能够使用基于集合的查询进行编程,有很多话要说。我讨厌听起来像 Celko,虽然偶尔光标肯定有一席之地,但它们通常是那些认为我们在 70 年代使用磁带或其他物理格式的人的默认思维方式......

标签: performance sql-server-2008 stored-procedures cursor


【解决方案1】:

首先,将您的游标声明更改为更高效的游标:

DECLARE C_TicketHistorie CURSOR
    LOCAL STATIC FORWARD_ONLY READ_ONLY
    FOR

接下来,您确定这些操作需要光标吗?例如,您的更新似乎可以作为单个基于集合的操作而不是游标和动态 SQL 来完成,特别是如果您知道可以由 @StatistikStatus 指示的列名集(这在哪里确定,由道路?)。以下是您可以一举生成基于集合的动态 SQL 更新而不是游标的方法:

DECLARE @sql NVARCHAR(MAX) = N'';

WITH x AS
(
    SELECT  
        -- why only use aliases for the tables you don't reference often?
        th.TicketID, th.Datum, th.tickethistorieid
    FROM 
        dbo.TicketHistorie AS th
        INNER JOIN dbo.Status AS st
          ON th.NeueStatusID = st.StatusID
        INNER JOIN dbo.StatuszuStatistikStatus as s 
          on s.status_ID = st.statusid
        INNER JOIN dbo.StatistikStatus as ss 
          on s.bewertung_id = ss.id
    WHERE     
      ss.id = 5 -- 5 = HNR Terminbestätigung 
      AND st.Name = N'Termin vereinbart'
     -- be smarter about date range queries!
      AND dbo.TicketHistorie.Datum >= '2011127'
)
SELECT @sql += N'UPDATE Statistik.dbo.terminauswertungab27122011 SET ['
       + @StatistikStatus+']='''
       + cast(@TicketHistorieID as NVARCHAR(36))+''''
       + ' WHERE ID = ' + cast(@ID as nvarchar) + ' -- nvarchar(WHAT)?
       and ['+@StatistikStatus+'] IS NULL;';

这里可能进行更多优化,但正如 cmets 建议的那样,如果没有更多信息,很难做到。

【讨论】:

  • 我认为这不是找到优化的正确方法。主要问题是为什么每次执行都需要越来越长的时间
  • @MariusKrämer - 我们不可能说。您需要添加一些分析代码来查看哪些具体的事情需要更长的时间,然后再提出一个更具体的问题。
猜你喜欢
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 2011-06-27
  • 1970-01-01
  • 2018-09-01
  • 1970-01-01
相关资源
最近更新 更多