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ツリーとして実装されていますか?値の組み合わせをどのように評価できますか?そのような機能の制限は何ですか?
行を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
の各個別の値内で個別のシークを実行する必要がありますが、これはサポートされていません(より具体的な場合を除いて、おそらく心配する必要はありません。パーティション分割テーブル)。
従来のインデックスは、単一列キーでも複数列キーでも、Bツリーとして実装されます。
そしてそれはどのようにクエリをスピードアップすることができます
SELECT ID, Ranking FROM Items where Category = 1 AND OfferState < 3
複合インデックスキーの順序は、クエリの最適化にとって重要です。最初に(選択性の順序で)等価述部で使用される列を指定し、次に、不等価述部で使用される列を指定します。これにより、等しい条件に一致する行のみを操作し、指定された範囲内の行にアクセスできるようになります。したがって、このクエリの場合、インデックスの列の順序は、その逆ではなく、CategoryとOfferStateである必要があります。
論理的には、個々の列はタプル(Category, OfferState)
。これらのタプルはインデックスキーであり、Bツリーアルゴリズムは変更されずに機能します。
Bツリーには、いかなる種類の「条件」も必要ありません。合計注文が定義されているバリュードメインで機能します。データ構造の意味で行われている唯一の操作は、2つのキーを比較することです。 SQL Serverはさらに2つの操作を使用します。バイトへのシリアル化とバイトからの逆シリアル化です。