第一次运行SQL Server T-SQL查询速度慢,然后快速运行

时间:2016-09-15 00:58:49

标签: sql-server tsql stored-procedures

我有一个非常简单的存储过程;它第一次运行缓慢,然后在相同的输入参数下快速运行。

它返回2个表,第一个表快速返回,但是第二个表,它变得很慢,因为我用表1结果加入它以获得正确的数据

这是我的存储过程代码:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[PR_ReadMdgObj]
      (@objId int,
       @dtFrom datetime = NULL,
       @dtTo datetime = NULL)
AS
BEGIN
    SET NOCOUNT ON

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

    DECLARE @engine_SensorSource_id INT

    SELECT @engine_SensorSource_id = SensorSourceid 
    FROM dbo.SensorSource 
    WHERE sourcenameid = 1 
      AND objectid = @objId  

    CREATE TABLE #10msgtable 
    (
        rownum int IDENTITY (1, 1) NOT NULL,
        MessageId bigint NOT NULL,
        ObjectId int NOT NULL,
        VectorAngle int NOT NULL,
        VectorSpeed int NOT NULL,
        Altitude int NOT NULL,
        GpsTime datetime NOT NULL,
        VisibleSatelites int NULL,
        X float, Y float,
        engine int,
        st int
    );

    CREATE CLUSTERED INDEX IDX_C_returnTable10_GpsTime 
    ON #10msgtable (GpsTime);

    INSERT INTO #10msgtable 
        SELECT 
            [Message].messageid, [Message].objectid, 
            [Message].vectorangle, [Message].vectorspeed, 
            [Message].altitude, [Message].gpstime, 
            [Message].visiblesatelites, 
            [Message].x, [Message].y, 
            0 Engine, 0 as t
        FROM   
            dbo.[Message] WITH (nolock) 
        WHERE  
            [Message].ObjectId = @objId
            AND [Message].GpsTime BETWEEN @dtFrom AND @dtTo 
            --  AND m.Valid = 1 
            -- AND m.VectorSpeed < 250 

    DELETE FROM #10msgtable 
    WHERE VectorSpeed = 250;

    SELECT * 
    FROM #10msgtable 
    ORDER BY GpsTime ASC

    --- select 2
    SELECT 
        MessageSensors.MessageId,
        SensorSource.SourceNameId,
        MessageSensors.Value 
    FROM 
        dbo.MessageSensors 
    INNER JOIN
        #10msgtable WITH (nolock) ON MessageSensors.MessageId= #10msgtable.MessageId
    INNER JOIN 
        dbo.SensorSource WITH (nolock) ON SensorSource.SensorSourceId = MessageSensors.SensorSourceId
    --where MessageSensors.MessageId in (select MessageId from #10msgtable)

    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
END

这是我的实际执行计划:

https://gist.github.com/aymanstar/3ed882c6330ee6252751ce9dd2f5beac

1 个答案:

答案 0 :(得分:0)

您添加的步骤很少。第一次运行总是很慢(因为你已经知道了)。 在你的脚本

  1. 无需添加with(nolock)原因由@marc_s
  2. 解释
  3. 不必要的变量声明(@engine_SensorSource_id)。
  4. 如果您在第一次尝试过滤掉数据,则无需执行delete
  5. 所以修改后的脚本应该是: -

    SET ANSI_NULLS ON
    GO
    
    SET QUOTED_IDENTIFIER ON
    GO
    
    ALTER PROCEDURE [dbo].[PR_ReadMdgObj] (
        @objId INT
        ,@dtFrom DATETIME = NULL
        ,@dtTo DATETIME = NULL
        )
    AS
    BEGIN
        SET NOCOUNT ON
        SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    
        --DECLARE @engine_SensorSource_id INT
    
        --SELECT @engine_SensorSource_id = SensorSourceid
        --FROM dbo.SensorSource
        --WHERE sourcenameid = 1
        --  AND objectid = @objId
    
        CREATE TABLE #10msgtable (
            rownum INT IDENTITY(1, 1) NOT NULL
            ,MessageId BIGINT NOT NULL
            ,ObjectId INT NOT NULL
            ,VectorAngle INT NOT NULL
            ,VectorSpeed INT NOT NULL
            ,Altitude INT NOT NULL
            ,GpsTime DATETIME NOT NULL
            ,VisibleSatelites INT NULL
            ,X FLOAT
            ,Y FLOAT
            ,engine INT
            ,st INT
            );
    
        CREATE CLUSTERED INDEX IDX_C_returnTable10_GpsTime ON #10msgtable (
            MessageId
            ,GpsTime
            );
    
        INSERT INTO #10msgtable
        SELECT [Message].messageid
            ,[Message].objectid
            ,[Message].vectorangle
            ,[Message].vectorspeed
            ,[Message].altitude
            ,[Message].gpstime
            ,[Message].visiblesatelites
            ,[Message].x
            ,[Message].y
            ,0 Engine
            ,0 AS t
        FROM dbo.[Message]
        WHERE [Message].ObjectId = @objId
            AND [Message].GpsTime BETWEEN @dtFrom
                AND @dtTo
            AND VectorSpeed <> 250
    
        --  AND m.Valid = 1 
        -- AND m.VectorSpeed < 250 
        --DELETE
        --FROM #10msgtable
        --WHERE VectorSpeed = 250;
    
        SELECT *
        FROM #10msgtable
        ORDER BY GpsTime ASC
    
        --- select 2
        SELECT MessageSensors.MessageId
            ,SensorSource.SourceNameId
            ,MessageSensors.Value
        FROM dbo.MessageSensors
        INNER JOIN #10msgtable ON MessageSensors.MessageId = #10msgtable.MessageId
        INNER JOIN dbo.SensorSource ON SensorSource.SensorSourceId = MessageSensors.SensorSourceId
    
        --where MessageSensors.MessageId in (select MessageId from #10msgtable)
        SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    END