web-dev-qa-db-ja.com

結合条件で使用される列にインデックスを適用する

以下のクエリで、結合条件で使用される列にインデックスを使用することはどれほど有益ですか?

_select * from table_a
inner join table_b on
           table_a.col1 = table_b.col1 and 
           table_a.col2 = table_b.col2
_

上記の結合では、テーブルtable_a(col1,col2)またはテーブルtable_b(col1,col2)にインデックスを付けることは有益ですか?また、インデックス内の列の順序はパフォーマンスに影響しますか?

table_b(col1,col2)にインデックスがあると仮定します。クエリを次のように変更する必要があるという意味ですか?

_select * from table_a
    inner join table_b on
               table_b.col1 = table_a.col1 and 
               table_b.col2 = table_a.col2
_
5
Madhusudan

Bツリーインデックスには、3つの主な利点があります。

  1. 特定の値または値の範囲にシークする
  2. インデックス順に行を返す
  3. 基本テーブルよりも小さい行サイズ(クラスター化インデックスまたはヒープ)

有用なインデックスがない場合、オプティマイザの主な結合戦略はhash joinです。この場合、小さいテーブルの結合キーを使用してハッシュテーブルを作成し、その後結合キーを使用します。より大きなテーブルから、そのハッシュテーブルを調べて一致を探します。ハッシュ結合には、完全なハッシュテーブルを保持するためのメモリが必要です。

有用なインデックスを使用して、オプティマイザはインデックス付きのネストされたループjoinまたはmerge join戦略:

インデックス付きネストループ結合

この物理的な結合戦略は、主に上記の利点#1を利用します。小さいテーブルから読み取り、次に結合キーの大きいテーブルのインデックスにシークします。等結合の場合、インデックスキーの順序は重要ではありません。インデックスキーが(col1, col2)でも(col1, col2)でも、(col2, col1)のシークは可能です。

たとえば、いずれかのテーブルの(col1, col2)または(col2, col1)のインデックスは、インデックス付きのネストされたループ結合戦略を有効にします。理想的には、インデックスはより大きなテーブルにあります。

マージ結合(明示的なソートなし)

この物理結合は、主に上記の利点#2(インデックス順)を使用します。インデックスには、両方のテーブルで同じキー順ですべての結合列を含める必要があります。 (col1, col2)のマージ結合は(col1, col2)または(col2, col1)のインデックスを使用できますが、キーの順序は両方のテーブルで同じである必要があります。

マージ結合は、少なくとも1つの入力が結合キーで一意であることが保証されている場合に最も効率的です。

たとえば、両方のテーブルの(col1, col2)または(col2, col1)のインデックスが必要になります。インデックスは両方で同じキー順序を持つ必要があり、理想的には、インデックスは少なくとも1つのテーブルのそれらの列で一意である必要があります。


db<>fiddleデモ


ON句の述語のテキスト順は重要ではありません。以下はまったく同じです。どちらを使用するかは、純粋にスタイルの問題です。

-- I prefer this style
SELECT * 
FROM dbo.table_a AS TA
JOIN dbo.table_b AS TB
    ON TB.col1 = TA.col1
    AND TB.col2 = TA.col2;

SELECT * 
FROM dbo.table_a AS TA
JOIN dbo.table_b AS TB
    ON TA.col1 = TB.col1
    AND TA.col2 = TB.col2;

より一般的には、インデックスが物理結合の選択にどのように影響するかは、方程式の一部にすぎません。インデックスは、クエリ内の他の(非結合)述語、および集計、ウィンドウ処理、最終的な表示順序などの他の操作に役立ちます。

クエリ全体およびワークロード内のすべてのクエリに対するインデックスの有用性と、それらのインデックスを維持するコストのバランスをとることは、データベースの管理とチューニングの重要な部分です。

9
Paul White 9

それを最大限に活用するには、両方のテーブルにインデックスを作成する必要があります。

ここで、クエリに応じて、最初に作成するインデックスを決定する必要があります。

インデックスの表面をひっかいただけのブログが見つかります here

また、インデックスが正しく機能しているかどうか、およびそれらのインデックスを使用しているかどうかを理解するために、実行プランを読み取ることができる必要もあります。

実行計画についてのブログは、次の場所にあります ここ

質問に答える:クエリオプティマイザーは、特に指定されていない限り(オプション(強制順序))、テーブルが結合される独自の計画と順序を作成するため、最初に初期化するテーブルに違いはありませんが、パフォーマンスは向上しませんもしあなたがそうするなら。

3
S4V1N