2012-02-04 70 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