2010-10-29 169 views
5

我正在運行一個程序,第一次執行需要大約1分鐘的時間,但下一次它會減少到大約9-10秒。過了一段時間,大約需要1分鐘。與下次運行相比,sql查詢需要很長時間

我的程序正在處理具有6個非聚簇索引和1個聚簇索引的單個表,並且唯一ID列是具有1,218,833行的唯一標識數據類型。

你能指導我問題在哪裏/可能的性能改進是什麼?

在此先感謝。

這是程序。

PROCEDURE [dbo].[Proc] (
     @HLevel NVARCHAR(100), 
     @HLevelValue INT, 
     @Date DATE, 
     @Numbers NVARCHAR(MAX)=NULL 
    ) 
    AS 

    declare @LoopCount INT ,@DateLastYear DATE 


    DECLARE @Table1 TABLE (list of columns) 
    DECLARE @Table2 TABLE (list of columns) 

    -- LOOP FOR 12 MONTH DATA 
    SET @LoopCount=12 
    WHILE(@LoopCount>0) 
     BEGIN 
      SET @LoopCount= @LoopCount -1 

      -- LAST YEAR DATA 
      DECLARE @LastDate DATE; 
      SET @LastDate=DATEADD(D,-1, DATEADD(yy,-1, DATEADD(D,1,@Date))) 




        INSERT INTO @Table1 
        SELECT list of columns 
         FROM Table3 WHERE Date = @Date 
        AND 
        CASE 
         WHEN @HLevel='crieteria1' THEN col1 
         WHEN @HLevel='crieteria2' THEN col2 
         WHEN @HLevel='crieteria3' THEN col3 
        END [email protected] 



        INSERT INTO @Table2 
         SELECT list of columns 
         FROM table4 
         WHERE Date= @LastDate 
         AND (@Numbers IS NULL OR columnNumber IN (SELECT * FROM dbo.ConvertNumbersToTable(@Numbers))) 

INSERT INTO @Table1 
     SELECT list of columns 
      FROM @Table2 Prf2 WHERE Prf2.col1 IN (SELECT col2 FROM @Table1) AND Year(Date) = Year(@Date) 



    SET @Date = DATEADD(D,-1,DATEADD(m,-1, DATEADD(D,1,@Date))); 

END 

    SELECT list of columns FROM @Table1 
+0

您是否嘗試過使用執行計劃給你什麼是與查詢發生的事情的想法?而且,它第一次運行時,會將執行計劃緩存在內存中,以便下次執行更快。 – 2010-10-29 07:54:48

+1

請顯示一些代碼,以便我們可以看看你在做什麼。 – 2010-10-29 07:57:36

+0

有沒有什麼方法可以手動添加執行計劃來加速並永久存在。 – Chingi 2010-11-03 08:44:23

回答

10

第一次運行查詢時,數據不在數據緩存中,因此必須從磁盤中檢索。此外,它必須準備一個執行計劃。在後續運行查詢的時候,數據將存儲在緩存中,因此它不需要到磁盤進行讀取。它也可以重用最初生成的執行計劃。這意味着執行時間可以更快,爲什麼理想的情況是擁有大量RAM以便能夠儘可能多地在內存中緩存數據(這是數據緩存提供了最大的性能改進)。

如果後續執行時間再次增加,則可能是數據正在從緩存中移除(並且執行計劃也可能從緩存中刪除) - 取決於RAM的壓力。如果SQL Server需要釋放一些,它會從緩存中刪除東西。最常使用/具有最高值的數據/執行計劃將保留更長時間的緩存。

當然也有其他的事情,可能是一個因素,例如是當時的服務器上什麼負載,查詢是否被阻止其它進程等

+0

有些猜測。在第一次執行後運行\\ CHECKPOINT \\ DBCC DROPCLEANBUFFERS()\\。如果後來的執行速度仍然很慢,那麼AdaTheDev就會出現。這是緩存。 因此,如果目標是讓查詢在所有情況下都能快速運行,則需要更多信息。 – 2010-10-29 13:07:35

+0

我已經添加了程序。 – Chingi 2010-11-03 08:43:29

+1

@Chingi - 你可以用程序做的最好的事情是重寫它以擺脫循環。如果要獲得良好的性能,通常應避免使用循環/光標。 – AdaTheDev 2010-11-03 08:51:10