クラスター化インデックススキャンの実行回数が非常に多いのはなぜですか?


15

同じクエリプランを生成する2つの類似したクエリがありますが、1つのクエリプランがクラスタ化インデックススキャンを1316回実行し、もう1つのクエリプランが1回実行することを除きます。

2つのクエリの唯一の違いは、異なる日付基準です。長時間実行されるクエリは、実際には日付基準を絞り込み、引き戻すデータを減らします。

両方のクエリに役立ついくつかのインデックスを特定しましたが、クラスター化インデックススキャン演算子が1回実行するクエリと実質的に同じクエリで1316回実行する理由を理解したいだけです。

スキャンされているPKの統計を確認しましたが、比較的最新です。

元のクエリ:

select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
    select incident_id as exported_incident_id
    from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-06-01 00:00:00.000' and '2011-07-01 00:00:00.000'
    and exported_incidents.exported_incident_id is not null

この計画を生成します。 ここに画像の説明を入力してください

日付範囲の基準を絞り込んだ後:

select distinct FIR_Incident.IncidentID
from FIR_Incident
left join (
    select incident_id as exported_incident_id
    from postnfirssummary
) exported_incidents on exported_incidents.exported_incident_id = fir_incident.incidentid
where FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'
    and exported_incidents.exported_incident_id is not null

この計画を生成します。 ここに画像の説明を入力してください


画像ファイルの代わりにコードブロックにクエリをコピー/貼り付けできますか?
エリックハンフリー-lotsahelp

確かに-各プランを生成するクエリを追加しました。
セイバー

クラスタ化インデックススキャンはどのテーブルで実行されますか?
エリックハンフリー-lotsahelp

クラスタ化インデックスのスキャンは、左の参加(PostNFIRSSummary)のサブクエリにある
Seibar

1
おそらく前回統計が更新されたときに、FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'基準を満たす行は1つまたは1つだけであり、それ以降、その範囲内に不均衡な数の挿入がありました。その日付範囲には1.07の実行のみが必要であると推定されます。実際に続いている1,316ではありません。
マーティンスミス

回答:


9

スキャン後のJOINからヒントが得られます。最後の結合(もちろん右から左に読む)の片側の行数が少ないため、オプティマイザーは「ハッシュ結合」ではなく「ネストされたループ」を選択します。

ただし、これを見る前に、キー検索とDISTINCTを排除することを目指します。

  • キールックアップ:FIR_Incidentのインデックスがカバーされている必要があります(FI_IncidentDate, incidentid)。または、両方を使用して、どちらがより頻繁に使用されるかを確認します(両方とも使用される場合があります)

  • DISTINCT結果ですLEFT JOIN ... IS NOT NULL。オプティマイザーは既にそれを削除しました(計画には最終的なJOINに「左半結合」があります)が、明確にするためにEXISTSを使用します

何かのようなもの:

select 
    F.IncidentID
from 
    FIR_Incident F
where 
    exists (SELECT * FROM postnfirssummary P
           WHERE P.incident_id = F.incidentid)
    AND
    F.FI_IncidentDate between '2011-07-01 00:00:00.000' and '2011-07-02 00:00:00.000'

プランガイドとJOINヒントを使用して、SQL Serverでハッシュ結合を使用できるようにすることもできますが、最初に正常に機能するようにしてください。ガイドまたはヒントは、データと将来ではなく、現在実行しているクエリ

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.