web-dev-qa-db-ja.com

where句にインデックスがある場合とない場合の2つの列-インデックスの機能

SQL Server 2008でクエリを実行しています:

SELECT col1
FROM table1
WHERE col2=val2 AND col3=val3

ここで、col2には非クラスター化インデックスがあり、col1はPRIMARY KEY、およびcol3にはインデックスがありません。クエリ実行プランはこれに似ています。 enter image description here

ここでクエリ実行の仕組みを知りたい。実行プランから、「col2」でのインデックスシークと「col3」でのキールックアップを確認できます(並行して表示)。

  • 'col2 = val2'条件に一致するすべての行をフェッチし、他の条件を確認しますか?
  • なぜこれら2つの-Index seekとKey-Lookupが実行プランで並行して表示されるのですか?
  • 大規模なデータセットを考慮し、「col2」のほとんどすべてのエントリが一意であると想定して、常に「col2」で使用可能なインデックスを使用しますか?
7
Rahul Raghavan

クエリ実行の仕組みを知りたい

一般的な実行モデルはパイプラインであり、各反復子が一度に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を指定する必要があります。

12
Paul White 9