与下次运行相比,sql查询需要很长时间

与下次运行相比,sql查询需要很长时间

问题描述:

我正在运行一个程序,第一次执行需要大约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

第一次运行查询时,数据不在数据缓存中,因此必须从磁盘中检索。此外,它必须准备一个执行计划。在后续运行查询的时候,数据将存储在缓存中,因此它不需要到磁盘进行读取。它也可以重用最初生成的执行计划。这意味着执行时间可以更快,为什么理想的情况是拥有大量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

看来,存储过程在反复重新编译一段时间。为了减少重新编译请查看这篇文章:

http://blog.sqlauthority.com/2010/02/18/sql-server-plan-recompilation-and-reduce-recompilation-performance-tuning/