2012-02-04 51 views
0

我有一个存储过程,它执行许多选择和使用某些游标进行更新。SQL Server存储过程减慢每次执行

当我第一次执行该程序时,大约需要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 [email protected] + @StatistikStatus+']=''' 
       SET @SQL [email protected] + cast(@TicketHistorieID as NVARCHAR(36))+'''' 
       SET @SQL [email protected] + ' WHERE ID = ' + cast(@ID as nvarchar) +' and ['[email protected]+'] IS NULL' 
       EXEC (@SQL) 

我使用SSMS调用过程。

在stp的开头,我删除了插入的表格。然后我做插入。表行是相同的每个执行

+1

使用[SSMS](http://msdn.microsoft.com/en-us/library/ms174173.aspx)调用存储过程时会发生这种情况吗?或只有当你从代码中调用它?我们需要更多关于proc的细节以及您如何使用它。 – yhw42 2012-02-04 14:55:44

+4

你需要提供更多的细节,没有人能做得比猜测更少。 – 2012-02-04 14:56:10

+1

我想最可能的原因是您在每次执行时处理更多数据 - 您是否将数据复制/移动到显示(意外)增长的表格?可能这不是你的程序执行速度太慢,而是你的数据库忙于分配更多空间。 – Filburt 2012-02-04 15:02:09

回答

2

首先,改变你的光标声明更有效的光标:

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 ['[email protected]+'] IS NULL;'; 

可能很多更可能的优化在这里,但因为意见建议,对没有更多的信息做艰难。

+0

我认为这不是找到优化的正确方法。主要问题是为什么每次执行所需的时间越长越长 – 2012-02-04 18:11:17

+0

@MariusKrämer - 我们无法说出口。您需要添加一些分析代码,以查看具体事情需要更长的时间,然后提出更具体的问题。 – 2012-02-04 18:53:33