2010-10-29 4 views
5

Je suis en cours d'exécution d'une procédure qui prend environ 1 minute pour la première exécution, mais pour la prochaine fois il réduit à environ 9-10 secondes. Et après un certain temps, cela prend environ 1 minute.SQL requête prend beaucoup de temps par rapport à la prochaine exécution

Ma procédure fonctionne avec une table unique qui comporte 6 index non cluster et 1 cluster et une colonne id unique est un type de données uniqueidentifier avec 1 218 833 lignes.

Pouvez-vous me guider où est le problème/l'amélioration des performances possibles est?

Merci d'avance.

Voici la procédure.

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

Avez-vous essayé d'utiliser le plan d'exécution pour vous donner une idée de ce qui se passe avec la requête? De plus, lors de la première exécution, le plan d'exécution sera mis en cache dans la mémoire, ce qui le rendra plus rapide la prochaine fois. –

+1

S'il vous plaît montrer du code afin que nous puissions voir ce que vous faites. –

+0

Existe-t-il des moyens d'ajouter des plans d'exécution manuellement pour accélérer et il sera là pour toujours. – Chingi

Répondre

10

Lors de la première exécution de la requête, les données ne se trouvent pas dans le cache de données et doivent donc être extraites du disque. En outre, il doit préparer un plan d'exécution. Les temps suivants, vous exécutez la requête, les données seront dans le cache et donc il n'aura pas à aller sur le disque pour le lire. Il peut également réutiliser le plan d'exécution généré à l'origine. Cela signifie que la durée d'exécution peut être beaucoup plus rapide et qu'une situation idéale consiste à disposer de grandes quantités de RAM pour pouvoir mettre en mémoire cache autant de données que possible (c'est le cache de données qui offre les meilleures performances). Si les temps d'exécution augmentent par la suite, il est possible que les données soient supprimées du cache (et les plans d'exécution peuvent également être supprimés du cache) - cela dépend de la pression pour la RAM. Si SQL Server doit en libérer, il supprimera des éléments du cache. Les plans de données/d'exécution les plus utilisés/ayant la plus grande valeur resteront plus longtemps en cache.

Il y a bien sûr d'autres choses qui pourraient être un facteur tel que quelle charge est sur le serveur au moment, si votre requête est bloquée par d'autres procédés, etc

+0

Quelques suppositions. Exécutez \\ CHECKPOINT \\ DBCC DROPCLEANBUFFERS() \\ après la première exécution. Si les exécutions suivantes sont encore lentes, alors AdaTheDev est sur place. C'est le cache. Donc, si le but est d'obtenir une exécution rapide de la requête dans toutes les circonstances, plus d'informations sont nécessaires. –

+0

J'ai ajouté la procédure. – Chingi

+1

@Chingi - la meilleure chose que vous pouvez faire avec la procédure est de le réécrire pour se débarrasser de la boucle. Les boucles/curseurs devraient généralement être évités si vous voulez de bonnes performances. – AdaTheDev

Questions connexes