結合アルゴリズムの選択基準

Oracle CBO は以下の要素を考慮して結合方式を選択します。

  • 結合する行数: 少量 × 少量 → NESTED LOOPS、大量 × 大量 → HASH JOIN
  • インデックスの存在: 結合キーにインデックスがあれば NESTED LOOPS が有利になりやすい
  • ソート済みデータの有無: 結合キー順にソート済みなら SORT MERGE JOIN のソートコストが減る
  • 利用可能なメモリ(PGA): HASH JOIN / SORT MERGE JOIN はメモリが不足すると TEMP SPILL が発生
  • 結合条件の種類: 等値(=)以外の不等値条件では HASH JOIN が使えず NESTED LOOPS か SORT MERGE JOIN になる

NESTED LOOPS(ネステッドループ結合)

何を表すか: 外側ループ(Outer / 駆動表)の各行について、内側ループ(Inner / 被駆動表)をスキャンして一致する行を結合する方式。

Plan Table 上での読み方

NESTED LOOPS ノードの直下に 2 つの子ノードが並びます。上が外側ループ(駆動表)、下が内側ループ(被駆動表)です。

  • 正常パターン: 駆動表が少数行(数十〜数百)、被駆動表が結合キーに対してインデックスアクセスできる場合
  • 問題パターン: 駆動表が大量行 → 内側ループが何万回も実行される(OLAP 的クエリでの NESTED LOOPS は非効率)
  • 閾値・注意点: ALLSTATS の Starts 列で内側ループの実行回数を確認。外側 Rows × Starts が内側ループの実際の起動数
NESTED LOOPS の種類と特徴
Operation意味注意点
NESTED LOOPS通常のネステッドループ結合内側が INDEX RANGE SCAN + TABLE ACCESS BY ROWID の組み合わせが典型
NESTED LOOPS OUTEROUTER JOIN(LEFT/RIGHT)のネステッドループ実装一致しない外側行に NULL 補完行を追加
NESTED LOOPS SEMIEXISTS / IN サブクエリを SEMI JOIN で実装最初の一致が見つかれば内側ループ終了(効率的)
NESTED LOOPS ANTINOT EXISTS / NOT IN の ANTI JOIN 実装一致した場合に行を除外。NULL の扱いに注意

HASH JOIN(ハッシュ結合)

何を表すか: Build 側(上のノード)の行セットをメモリ上のハッシュテーブルに展開し、Probe 側(下のノード)を流し込んで一致する行を結合する方式。大規模テーブル同士の等値結合に最適。

Plan Table 上での読み方

HASH JOIN ノードの上の子が Build 側(小さいほうの表を選ぶのが理想)、下の子が Probe 側です。

  • 正常パターン: 大規模テーブル同士の等値結合。Build 側に小テーブルが配置されている
  • 問題パターン①: Build 側が大きすぎてメモリに収まらず TEMP SPILL(HASH JOIN BUFFERED)が発生 → PGA 増量かバッチ分割を検討
  • 問題パターン②: 不等値結合(>=、<=)では HASH JOIN が使えない(オプティマイザが自動的に別方式を選ぶ)
  • 閾値・注意点: Build 側の Bytes が PGA_AGGREGATE_TARGET の約 5% を超えると SPILL が疑われる
HASH JOIN の種類と特徴
Operation意味注意点
HASH JOIN通常の内部結合版ハッシュ結合等値条件必須。最も一般的
HASH JOIN OUTEROUTER JOIN のハッシュ結合実装Build 側が外部表(結果に残す側)
HASH JOIN SEMIEXISTS / IN のハッシュ SEMI JOIN重複除去が内包される
HASH JOIN ANTINOT EXISTS / NOT IN のハッシュ ANTI JOINNULL を含む NOT IN は全行 NULL のケースで誤動作に注意
HASH JOIN RIGHT OUTER右外部結合のハッシュ実装Build/Probe の順が逆転

SORT MERGE JOIN(ソートマージ結合)

何を表すか: 両テーブルを結合キーでソートしてから、マージして結合する方式。ソート済みの結果セットに対しては効率的で、ORDER BY が後続する場合にはソートの再利用が可能。

  • 正常パターン: データが既にソート済み(パーティションキー順など)・ORDER BY と結合キーが一致・不等値結合(>、< 等)
  • 問題パターン: 大規模テーブルの等値結合で HASH JOIN の方が PGA 消費が少ないのに SORT MERGE JOIN が選ばれた場合(統計情報の誤りが原因なことが多い)
  • 閾値・注意点: 両テーブルの Bytes が大きいと 2 回のソートで TEMP SPILL が発生する可能性あり

MERGE JOIN CARTESIAN(直積)

何を表すか: 結合条件なし(またはすべてのクロス結合)で 2 つの表の全行を掛け合わせた直積を生成する結合。意図的な CROSS JOIN でない限り 計画に出現したら要警戒です。

  • 読み方: Rows = 左の行数 × 右の行数(爆発的増加)
  • 問題パターン: 結合条件の書き忘れ(テーブル間に ON 句がない)・FROM 句に結合条件のない表が含まれている・サブクエリのスカラー化でカーティシャンが発生
  • 閾値・注意点: 数百万行の直積はメモリ・TEMP を瞬時に枯渇させる。計画に見えたらまず SQL の結合条件を確認する
  • 正常パターン: 意図的な CROSS JOIN(すべての組み合わせが必要なビジネスロジック)

結合方式の比較表

比較項目NESTED LOOPSHASH JOINSORT MERGE JOIN
等値結合
不等値結合
大規模 × 大規模△(遅い)
小規模 × 大規模(インデックスあり)
ソート済みデータへの効率影響なし影響なし◎(ソートコスト削減)
メモリ消費少ない多い(Build 側分)多い(ソート分×2)
TEMP SPILL リスク低いありあり
強制ヒントUSE_NL(table)USE_HASH(table)USE_MERGE(table)