MicrosoftのSQL Serverのカバリングインデックスとカバリングクエリの概念と関係を説明できますか?
カバリングインデックスは、クラスター化インデックスをさらに検索することなく、クエリで要求されたすべての列を満たすことができるインデックスです。
カバーするクエリのようなものはありません。
このSimple-Talkの記事をご覧ください: カバリングインデックスを使用したクエリパフォーマンスの改善 。
すべての列がクエリのselect
リストで要求されている場合、インデックスで利用可能であれば、クエリエンジンはテーブルを再度ルックアップする必要はありません。クエリのパフォーマンスを大幅に向上させることができます。要求されたすべての列はインデックスで使用できるため、インデックスはクエリをカバーしています。そのため、クエリはカバーリングクエリと呼ばれ、インデックスはカバーリングインデックスです。
選択リストの列が同じテーブルにある場合、クラスター化インデックスは常にクエリをカバーできます。
インデックスの概念に慣れていない場合は、次のリンクが役立ちます。
カバリングインデックスはNon-Clustered
インデックス。クラスター化インデックスと非クラスター化インデックスはどちらもBツリーデータ構造を使用してデータの検索を改善しますが、違いはクラスター化インデックスのリーフではレコード全体(つまり行)が物理的にすぐそこに格納されることですが、これはそうではありません!非クラスター化インデックスの場合。次の例で説明します。
例:ID、Fname、Lnameの3つの列を持つテーブルがあります。
ただし、非クラスター化インデックスの場合、2つの可能性があります。テーブルにクラスター化インデックスが既にあるか、ないかのどちらかです。
2つの図が示すように、このような非クラスター化インデックスは、Bツリーだけからお気に入りの値(つまり、Lname)を見つけることができないため、良好なパフォーマンスを提供しません。代わりに、Lnameの値を見つけるために、追加のルックアップステップ(キーまたはRIDルックアップ)を実行する必要があります。そして、これは、カバーされたインデックスが画面に来る場所です。ここで、IDの非クラスタ化インデックスは、その右のLnameの値をカバーしますB-Treeから離れて、ルックアップのタイプはもう必要ありません。
対象クエリは、クエリの結果セットのすべての列が非クラスター化インデックスから取得されるクエリです。
インデックスの適切な配置により、クエリはカバーされたクエリになります。
多くの場合、非クラスター化インデックスはクラスター化インデックスまたはヒープインデックスよりもページあたりの行数が多いため、カバードクエリは非カバードクエリよりもパフォーマンスが高いため、クエリを満たすためにメモリに取り込む必要があるページが少なくなります。テーブル行の一部のみがインデックス行の一部であるため、ページあたりの行数が多くなります。
カバリングインデックスは、対象クエリで使用されるインデックスです。それ自体がカバーインデックスであるインデックスのようなものはありません。インデックスは、クエリAに対するカバーリングインデックスであると同時に、クエリBに対するカバーリングインデックスではない場合があります。
devx.comの記事 は次のとおりです。
SQLクエリで使用されるすべての列を含む非クラスター化インデックスの作成、インデックスカバーリングと呼ばれる手法
covered queryは、返されたレコードセットのすべての列をカバーするインデックスを持つクエリであるとしか想定できません。 1つの注意点-インデックスとクエリは、SQLサーバーがクエリからインデックスが有用であると実際に推測できるように構築する必要があります。
たとえば、テーブルの結合自体は、そのようなインデックスの恩恵を受けない場合があります(SQLクエリ実行プランナーのインテリジェンスによって異なります)。
PersonID ParentID Name
1 NULL Abe
2 NULL Bob
3 1 Carl
4 2 Dave
PersonID,ParentID,Name
にインデックスがあると仮定しましょう。これは、次のようなクエリのカバーインデックスになります。
SELECT PersonID, ParentID, Name FROM MyTable
しかし、このようなクエリ:
SELECT PersonID, Name FROM MyTable LEFT JOIN MyTable T ON T.PersonID=MyTable.ParentID
すべての列がインデックスに含まれていても、おそらくそれほどメリットはありません。どうして? PersonID,ParentID,Name
のトリプルインデックスを使用したいということを本当に言っているわけではないからです。
代わりに、2つの列-PersonID
とParentID
(Name
は省略されます)に基づいて条件を構築し、すべてのレコードを要求しています。列PersonID, Name
。実際には、実装に応じて、インデックスが後半部分に役立つ場合があります。ただし、最初の部分では、他のインデックスを使用する方が適切です。
カバリングインデックスは、必要なすべての列を提供し、SQLサーバーがクラスター化インデックスに戻って列を見つける必要がないインデックスです。これは、非クラスター化インデックスを使用し、列をカバーするINCLUDEオプションを使用して実現されます。非キー列は、非クラスター化インデックスにのみ含めることができます。キー列とINCLUDEリストの両方で列を定義することはできません。 INCLUDEリストで列名を繰り返すことはできません。非キーインデックスが最初に削除された後にのみ、非キー列をテーブルから削除できます。 詳細はこちらをご覧ください
カバーするクエリは、基礎となるテーブルのインデックスを使用してすべての述語を照合できる場所にあります。
これは、検討中のSQLのパフォーマンスを向上させるための最初のステップです。
クラスター化インデックスが、定義されたテーブル内のすべての列のキー順に並べられた非ヒープリストで構成されていることを思い出したとき、ライトが点灯しました。 「クラスター」という言葉は、その「ホットスポット」に魚のクラスターのように、すべての列の「クラスター」があるという事実を指します。求められた値を含む列をカバーするインデックスがない場合(方程式の右側)、実行プランは、他のどの列にも要求された列が見つからないため、要求された列のクラスタ化インデックスの表現にクラスタ化インデックスシークを使用します「カバー」インデックス。不足すると、提案された実行計画でクラスター化インデックスシーク演算子が発生します。この場合、求められる値はクラスター化インデックスで表される順序付きリスト内の列内にあります。
そのため、1つの解決策は、インデックス内に要求された値を含む列を持つ非クラスター化インデックスを作成することです。この方法では、クラスター化インデックスを参照する必要がなく、オプティマイザーはヒントなしで実行プランでそのインデックスをフックできる必要があります。ただし、単一列クラスタリングキーとクラスタリングキーのスカラー値への引数に名前を付ける述語がある場合、クラスター化インデックスシーク演算子は、2番目の列に既にカバーインデックスがある場合でも使用されますインデックスなしのテーブル。