web-dev-qa-db-ja.com

SQL Serverで結合インデックスはどのように実装されますか

SQL Serverで単一のインデックス付き列がどのように機能するか、およびバランスツリーを使用してどのように実装されるかを理解しています。このトピックにはたくさんの YouTubeの興味深いビデオ があります。ただし、インデックスが複数の列に基づいている場合、それがどのように機能するのかわかりません。例えば:

CREATE NONCLUSTERED INDEX idxItemsCatState
ON Items (Category,OfferState)
INCLUDE ([Id],[Ranking])

そしてそれはどのようにクエリをスピードアップすることができます

SELECT ID, Ranking FROM Items where Category = 1 AND OfferState < 3

それはまだBツリーとして実装されていますか?値の組み合わせをどのように評価できますか?そのような機能の制限は何ですか?

4
Tomas Kubes

行をBツリーに格納してシークを実行するには、行をソートする順序が必要です。 (Category)でソートできるのと同じように、タプル(Category, OfferState)でもソートできます。後者の場合、行は最初にCategoryでソートされ、次にOfferStateでソートすることですべてのタイが分割されます。

結果のインデックスは同じbツリー構造を使用しますが、bツリーの各エントリの値は(Category, OfferState)タプルになります。

そしてそれはどのようにクエリをスピードアップすることができます...

クエリの場合、SQL Serverは次の方法でシークを実行できます。

  • Category = 1に一致する最初の行を探します。これは、おなじみの同じbツリーシークを使用して実行できます。SQLServerでは、各(Category, OfferState)タプルのCategory部分を使用するだけで済みます。
  • 行の読み取りを開始し、OfferState >= 3の行が見つかるまで続行します

このようにして、SQL Serverは必要な行の範囲の先頭に直接シークし、それらの行を読み取り、行の範囲の最後で停止することができます。クエリプランのSeek Predicate演算子のIndex Seekプロパティを見ると、このシークの動作を確認できることに注意してください。

より一般的には、(a, b, c, d, ...)列をまたぐ複数列インデックスは、((a)を使用して)等価性を一致させる場合、(a, b, c)または=などの列の先行サブセットのシークをサポートできます。

範囲(たとえば、b < 3)を探している場合、SQL Serverはインデックスの後半にある列を検索できなくなります。このような場合、bの各個別の値内で個別のシークを実行する必要がありますが、これはサポートされていません(より具体的な場合を除いて、おそらく心配する必要はありません。パーティション分割テーブル)。

5
Geoff Patterson

従来のインデックスは、単一列キーでも複数列キーでも、Bツリーとして実装されます。

そしてそれはどのようにクエリをスピードアップすることができます

SELECT ID, Ranking FROM Items where Category = 1 AND OfferState < 3

複合インデックスキーの順序は、クエリの最適化にとって重要です。最初に(選択性の順序で)等価述部で使用される列を指定し、次に、不等価述部で使用される列を指定します。これにより、等しい条件に一致する行のみを操作し、指定された範囲内の行にアクセスできるようになります。したがって、このクエリの場合、インデックスの列の順序は、その逆ではなく、CategoryとOfferStateである必要があります。

4
Dan Guzman

論理的には、個々の列はタプル(Category, OfferState)。これらのタプルはインデックスキーであり、Bツリーアルゴリズムは変更されずに機能します。

Bツリーには、いかなる種類の「条件」も必要ありません。合計注文が定義されているバリュードメインで機能します。データ構造の意味で行われている唯一の操作は、2つのキーを比較することです。 SQL Serverはさらに2つの操作を使用します。バイトへのシリアル化とバイトからの逆シリアル化です。

3
usr