SQL Server 2008でクエリを実行しています:
SELECT col1
FROM table1
WHERE col2=val2 AND col3=val3
ここで、col2には非クラスター化インデックスがあり、col1はPRIMARY KEY
、およびcol3にはインデックスがありません。クエリ実行プランはこれに似ています。
ここでクエリ実行の仕組みを知りたい。実行プランから、「col2」でのインデックスシークと「col3」でのキールックアップを確認できます(並行して表示)。
クエリ実行の仕組みを知りたい
一般的な実行モデルはパイプラインであり、各反復子が一度に1行を返します。実行はルートイテレータ(左端、例ではSELECT
とラベル付けされています)から始まります。
初期化後、ルートイテレータはその直接の子から行を要求し、以下同様に、行を返すことができるイテレータが見つかるまでチェーンを下っていきます。これにより、チェーンがルートに戻り、クライアントへのディスパッチのためにキューに入れられます。これは非常に簡略化された概要です。詳細については、以下を参照してください。
'col2 = val2'条件に一致するすべての行をフェッチし、他の条件を確認しますか?
非クラスター化インデックスのシークは、col2=val2
に一致する行を見つけます。 col2およびcol1を返すことができます(出力リストを参照) )col1がインデックスに存在するため(この場合、主キーがクラスター化されているため)。
この行はネストされたループ結合に渡され、次にキールックアップに制御を渡します。ルックアップでは、col1値を使用してクラスター化インデックスbツリーを検索し、col3この行。値は述語col3=val3
に対してテストされ、一致する場合にのみ返されます。
一致がある場合、行(c1、c2、c3)はチェーンに渡され、クライアントへの送信のためにキューに入れられます。コントロールがツリーを再び下降すると、非クラスター化インデックス内のcol2の新しい一致は、ネストされたループの結合の繰り返しになります->ルックアップ->リターン行サイクル。非クラスター化インデックスのシークが行を使い果たすとすぐに、制御が次にルートイテレーターに戻ったときにプロセスが完了します。
なぜこれら2つの-Index seekとKey-Lookupが実行プランで並行して表示されるのですか?
これが、グラフィカルなプランのレイアウト方法です。実行プロセスを詳細に理解する正しい方法については、上記のリンクと説明を参照してください。
大規模なデータセットを考慮し、「col2」のほとんどすべてのエントリが一意であると想定して、常に「col2」で使用可能なインデックスを使用しますか?
おそらくはい。オプティマイザは、利用可能な戦略の中からコストベースの選択を行います。予想される一致が非常に少ない場合、オプティマイザは通常、ルックアップ付きの非クラスタ化インデックスシークを最も安価なオプションとして評価します。テーブルが非常に小さい場合、例外が発生します。その場合、クラスター化インデックスをスキャンし、両方の述語を各行に適用すると、最も安価に見える可能性があります。
最後の注意として、ルックアップを回避する非クラスター化インデックスのカバーは次のとおりです。
CREATE [UNIQUE] NONCLUSTERED INDEX [dbo.table1 col2,col3 (col1)]
ON dbo.table1 (col2, col3)
INCLUDE (col1);
(col2、col3)に該当する場合は、UNIQUE
を指定する必要があります。