2016-09-15 190 views
0

我有一個非常簡單的存儲過程;它第一次運行緩慢,如果輸入參數相同,則運行速度很快。第一次運行SQL Server T-SQL查詢速度慢,然後快速運行

它返回兩個表,表頭正在迅速恢復,但第二個表,它作爲我與表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

+3

能運行得更快是因爲查詢和執行計劃被緩存的原因。這意味着如果參數不改變,查詢會更快,第二次運行時它會更快 – luchosrock

+0

我知道,但是,如何優化查詢以及爲什麼它會變慢?它的正常讀數沒有任何複雜的計算 –

+2

「第一次運行」是什麼意思?就像重新啓動SQL Server之後一樣?首次運行速度通常會很慢,因爲所有數據都必須從磁盤讀取到內存中。一旦數據被緩存,在後續運行中會更快,除非在此期間再次強制數據從內存中溢出。如果執行計劃被緩存,則不太可能引起顯着差異;雖然不是不可能,但編譯本身不太可能造成顯着的,明顯的延遲(除非SQL Server此次生成效率更低的計劃)。 –

回答

0

有你添加一些不必要的步驟。第一次運行總是很慢(正如你已經知道的那樣)。 在你的腳本

  1. 沒有必要添加with(nolock)的原因是由@marc_s
  2. 不必要的變量聲明(@engine_SensorSource_id)explaned。
  3. 如果您在第一次嘗試中過濾掉數據,則無需執行delete

所以修改後的腳本應該是這樣的: -

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 
+0

@ engine_SensorSource_id爲下一個建議,因爲我將在稍後使用它,因爲此列不包含在索引中,並且原始表很大,所以我從返回的結果中篩選, (無鎖),我同意沒有它的需要,但它不會延遲讀取速度? –

相關問題