2016-09-15 4 views
0

非常に単純なストアドプロシージャがあります。最初はゆっくりと実行され、同じ入力パラメータの場合は速く実行されます。SQL ServerのT-SQLクエリが最初の実行には遅く、その後は高速に実行されます。

それは最初のテーブルが速く返され、2つのテーブルを返しますが、私は、正しいデータを取得するために、表1の結果と、それに参加するように、第2の表は、それが遅くなった

ここ

私のストアドプロシージャのコードは次のとおりです。

ここで
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. 理由が不要な変数宣言(@engine_SensorSource_id)@marc_s
  2. によってexplanedさwith(nolock)を追加する必要はありません。
  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は、私は後で使用するので、私はこの列はインデックスに含まれていないと元のテーブルが大きいので、私は返された結果、 (ロックなし)、私はそれの必要はないことに同意しましたが、それは読み込み速度を遅らせることはありませんか? –

関連する問題