web-dev-qa-db-ja.com

パラメータ化されたクエリのパフォーマンスを向上させる

以下のクエリ実行プランのリンクに示されている(ストアドプロシージャ内の)SQL Server 2008 R2クエリのパフォーマンスを向上させる必要があります。

現在、約7秒で実行され、可能であれば1〜2秒で完了する必要があります。遅いクエリの各実行は常に約7秒です。クエリの結果は少しずつ流れていきます。照会されるテーブルは大きいが、数十億行ではない。

行数

Row Counts

渡されるパラメーターに応じて、結果は数百行(1秒未満で実行)から> 300K行(これは遅い)のいずれかになります。

スロークエリ実行プラン とオプティマイザで使用されているインデックスを含めました。これは より迅速な実行のための計画 および_STATISTICS IO, TIME_です。

AsIs StatsIO_Time

2つのクエリが実行されています。最初のものは問題ではありません。それは私が助けを必要とする2番目のものです。 SARGableでない述語(AND FT.TripDistance < ( CONVERT(NUMERIC(10,0),FT.TripTime) * 83.33 ))を削除することは必要ですが、速度にわずかな違いがあります

remove non SARG

関数[FN_GetLocalTime_FromUTC_BasedOnTZId]を削除すると、速度にわずかな違いが生じます。ここに_STATISTICS IO TIME_があり、SARG以外のwhere句と関数の両方を削除しています。ここに 実行計画 があります

remove non SARG and Func

_LOOP JOIN_ヒ​​ントを追加する以外の変更されていないクエリの出力を次に示します。これは遅いです。

LoopJoin

遅い変更のないクエリプランでは、_FACT_trip_Statuses_テーブルのインデックスシークの実際の行数(300330)が最終出力(299887)に近いことに気付きました。ただし、_xFactTrip_Annex_、_FACT_Trip_、および_FACT_Trip_Attributes_でのインデックスシークの実際の行数(4.87m)は異常です。どうすれば修正できますか? _OPTION RECOMPILE_を追加しても、ほとんど違いはありません

トレースフラグ4199 DBCC TRACEON (4199, -1);を追加して、JOINヒントを付けて、または付けずに再試行しましたが、役に立ちませんでした。

HASH結合ヒントとTF 4199

HASH join hint and TF4199

LOOP結合ヒントとTF 4199

LOOP join hint and TF4199

結合のヒントとTF 4199

No JOIN hints and TF4199

指数

_CREATE NONCLUSTERED INDEX IDX_FACT_Trip_StartDateUTC_VehicleKey_Includes ON dbo.FACT_Trip
(
    StartDateUTC ASC,
    VehicleKey ASC,
    EndDateUTC ASC
)
INCLUDE (   DriverKey,
    DrivingTime,
    TripDistance,
    TripTime)

CREATE NONCLUSTERED INDEX IX_xFactTrip_Annex_StartDateUTC_MonthlyProcessing ON dbo.xFactTrip_Annex
(
    StartDateUTC ASC
)
INCLUDE (   VehicleKey,
            Spd20Count, Spd20Distance,
            Spd30Count, Spd30Distance,
            Spd40Count, Spd40Distance,
            Spd50Count, Spd50Distance,
            Spd60Count, Spd60Distance,
            Spd70Count, Spd70Distance,
            SpdCat1,SpdCat2,SpdCat3,
            TotalIdling,
            PTOTime,
            TripFuel) 

CREATE NONCLUSTERED INDEX IX_FACT_Trip_Attributes_StartDateUTC_VehicleKey_Includes ON dbo.FACT_Trip_Attributes
(
    StartDateUTC ASC,
    VehicleKey ASC,
    EndDateUTC ASC
)
INCLUDE (   Attribute0Distance,
    Attribute1Distance,
    Attribute2Distance,
    Attribute3Distance,
    Attribute4Distance,
    Attribute5Distance,
    Attribute6Distance,
    Attribute7Distance,
    Attribute8Distance,
    Attribute9Distance,
    Attribute10Distance)

CREATE NONCLUSTERED INDEX IDX_FACT_Trip_Statuses_StartDateUTC_VehicleKey_Includes ON dbo.FACT_Trip_Statuses
(
    VehicleKey ASC,
    StartDateUTC ASC,
    EndDateUTC ASC
)
INCLUDE (   HarshAccelerationCount,
    HarshBrakeCount,
    HarshBumpCount,
    HarshCorneringCount,
    ExcessIdleDuration,
    ExcessIdleCount,
    OverspeedCount)

CREATE NONCLUSTERED INDEX IX_StartDateUTC_VehicleKey_IsBP ON dbo.FACT_TripComments
(
    StartDateUTC ASC
)
INCLUDE (   VehicleKey, IsBusinessPrivate) 
_
7
Mazhar

おそらく、#xMobiles一時テーブルに対するクラスター化インデックスは、最後の結合に役立ちます。

CREATE CLUSTERED INDEX IDX_xMobiles_VehicleKey ON #xMobiles
(
    VehicleKey ASC,
) 

最適なオプションは、テーブルにデータを入力した後でインデックスを作成することです。

1
Pablo Paredes

さて、このクエリにはまだ障害があり、データに対してテストすることはできませんが、同じ結果が得られ、少し速く実行されますか?

WITH cteBusGrps
  AS(
   SELECT
    LTRIM(RTRIM(CAST(A.Value AS INT))) 'BusGrpId', BG.BusinessGroupKey
   FROM
    dbo.FN_SplitString_AB (@nvBusGrpIds_csv, ',') A
   CROSS APPLY
    Warehouse.dbo.DIM_BusinessGroup BG
   WHERE
    vn = 1 
   AND
    BG.CtrackNodeID = CAST(A.Value AS INT)
  )
  INSERT INTO #xMobiles
  (
     NodeId
   , VehicleKey
   , VehicleId
   , CostCentreName
   , BusGrpId
   , BusGrpKey
   , AssignStart
   , AssignEnd
   , vGrpId
   , vGrpName
  )
  SELECT 
    V.vNodeId
   ,V.VehicleKey
   ,CAST(V.VehicleId AS NVARCHAR(50))
   ,V.CostCentreName
   ,V.BusGrpId
   ,V.BusinessGroupKey
   ,V.CreateDate
   ,COALESCE(V.DeletedTime,V.DeInstalled_DT,'2100-12-31 23:59:59') 
   ,V.vGrpId
   ,CAST(V.vGrpName AS NVARCHAR(100))
  FROM
   dbo.xED_Mobiles_OCC_ViewTable V
  INNER JOIN
   cteBusGrps      B ON B.BusinessGroupKey = V.BusinessGroupKey
  WHERE
   (
    ( CreateDate <= @dtStartDate_LT AND DeletedTime IS NULL ) 
    OR ( CreateDate <= @dtStartDate_LT AND DeletedTime BETWEEN @dtStartDate_LT AND @dtEndDate_LT )
    OR ( CreateDate BETWEEN @dtStartDate_LT AND @dtEndDate_LT ) 
    OR ( @dtStartDate_LT BETWEEN CreateDate AND COALESCE(V.DeletedTime,V.DeInstalled_DT,'2100-12-31 23:59:59')
  ) 

   SELECT
     M.BusGrpKey
    ,M.VehicleKey
    ,M.AssignStart
    ,M.AssignEnd
    ,FT.StartDateUTC
    ,D.LocalStartDateTime
    ,D.LocalEndDateTime
    ,CASE WHEN ISNULL(FT.DriverKey,0) < 1 THEN 0 ELSE ISNULL(FT.DriverKey,0) END 
            'DriverKey'
    ,CASE WHEN ISNULL(FT.DriverKey,0) < 1 THEN 1 ELSE 0 END
            'UnknownTrips'
    ,FTS.HarshAccelerationCount
    ,FTS.HarshBrakeCount
    ,FTS.HarshBumpCount
    ,FTS.HarshCorneringCount
    ,FTS.ExcessIdleDuration
    ,FTS.ExcessIdleCount
    ,FTS.OverspeedCount
    ,A.Spd20Count
    ,A.Spd20Distance
    ,A.Spd30Count
    ,A.Spd30Distance
    ,A.Spd40Count
    ,A.Spd40Distance
    ,A.Spd50Count
    ,A.Spd50Distance
    ,A.Spd60Count
    ,A.Spd60Distance
    ,A.Spd70Count
    ,A.Spd70Distance
    ,FT.TripDistance
    ,CONVERT(NUMERIC(10,0),FT.TripTime) * 83.33 'Ignore'
    ,FT.DrivingTime
    ,A.TotalIdling
    ,A.PTOTime
    ,FT.TripTime
    ,CAST( A.TripFuel AS DECIMAL(10,3))
            'TripFuel'
    ,CASE 
      WHEN CAST( A.TripFuel AS DECIMAL(10,3)) > 0 
       THEN FT.TripDistance
      ELSE 0
     END      'Tot_TF_DistTravelled'
    ,A.SpdCat1
    ,CAST(A.SpdCat2 AS INT)  'SpdCat2'
    ,CAST(A.SpdCat3 AS INT)  'SpdCat3'
    ,CASE   --EX-660
     WHEN FTA.Attribute0Distance > 0  THEN 0 
     WHEN FTA.Attribute1Distance > 0  THEN 1
     WHEN FTA.Attribute2Distance > 0  THEN 2
     WHEN FTA.Attribute3Distance > 0  THEN 3
     WHEN FTA.Attribute4Distance > 0  THEN 4
     WHEN FTA.Attribute5Distance > 0  THEN 5
     WHEN FTA.Attribute6Distance > 0  THEN 6
     WHEN FTA.Attribute7Distance > 0  THEN 7
     WHEN FTA.Attribute8Distance > 0  THEN 8
     WHEN FTA.Attribute9Distance > 0  THEN 9
     WHEN FTA.Attribute10Distance > 0 THEN 10
     ELSE 0
     END        'AttributeTypeId'
    ,ISNULL( TC.IsBusinessPrivate,0 ) 'BPOverride'
   FROM
    #xMobiles        M
   INNER JOIN
    Warehouse.dbo.FACT_Trip    FT ON FT.VehicleKey = M.VehicleKey
               AND FT.StartDateUTC BETWEEN @dtStartDate_LT AND @dtEndDate_LT
               AND FT.TripDistance < CONVERT(NUMERIC(10,0),FT.TripTime) * 83.33
   INNER JOIN
    dbo.xFactTrip_Annex      A ON A.VehicleKey = FT.VehicleKey
               AND A.StartDateUTC = FT.StartDateUTC
   INNER JOIN
    Warehouse.dbo.FACT_Trip_Statuses FTS ON FTS.VehicleKey = FT.VehicleKey
               AND FTS.StartDateUTC= FT.StartDateUTC
   INNER JOIN 
    Warehouse.dbo.FACT_Trip_Attributes FTA ON FTA.VehicleKey = FT.VehicleKey 
               AND FTA.StartDateUTC= FT.StartDateUTC
   LEFT JOIN
    Warehouse.dbo.FACT_TripComments  TC ON TC.VehicleKey = FT.VehicleKey
               AND TC.StartDateUTC = FT.StartDateUTC
   CROSS APPLY
    dbo.FN_GetLocalTime_FromUTC_BasedOnTZId(FT.StartDateUTC, FT.EndDateUTC, 2) D
   WHERE
   (
    ( FT.StartDateUTC BETWEEN M.AssignStart AND M.AssignEnd )
    OR ( M.AssignStart <= FT.StartDateUTC AND M.AssignEnd BETWEEN FT.StartDateUTC AND FT.EndDateUTC )
   ) 
0
Rich Benner