前回の記事では、結合の3大アルゴリズム(Nested Loop / Sort Merge / Hash)の概要について触れました。今回は、その中でも実務で最も頻繁に登場し、かつチューニングの要となる**「入れ子ループ法(Nested Loop Join)」**を深く掘り下げます。
まずは、試験でもよく問われる「高速化のポイント」を問題形式で確認してみましょう。
1. 今日のクイズ:入れ子ループ法の高速化
問題 入れ子ループ法(Nested Loop Join)において、結合処理を劇的に高速化するために最も効果的な対策はどれか?
(ア) 外側の表(駆動表)を事前に全件ソートする
(イ) 内側の表の結合キーに対してインデックスを作成する
(ウ) ワークエリア(メモリ)のサイズを拡張する
(エ) 等価結合を非等価結合(不等号など)に変更する
正解: (イ)内側の表の結合キーに対してインデックスを作成する
2. なぜ「内側のインデックス」が重要なのか?
入れ子ループ法の動きを思い出してみましょう。外側の表から1行取り出すたびに、内側の表を「探しに行く」のがこのアルゴリズムです。
インデックスがない場合: 外側の表が1,000件、内側の表が10,000件あると、最悪
1,000 × 10,000 = 1,000万回のデータアクセスが発生します。これが「重いクエリ」の正体です。インデックスがある場合: 内側の表を全件探す必要がなくなり、インデックスを使ってピンポイントでデータを見つけられます。計算量は劇的に減り、数秒かかっていた処理がコンマ数秒で終わるようになります。
3. 実務で差がつく「外側の表(駆動表)」の選び方
試験問題から一歩踏み込んで、現場で実行計画を見る際のポイントを解説します。入れ子ループ法では、どちらの表を「外側(駆動表)」にするかが運命を分けます。
鉄則:外側には「絞り込まれた後の件数」が少ない方を置く
例えば、「2024年の売上データ(100件)」と「商品マスタ(10万件)」を結合する場合を考えてみましょう。
正解: 売上データを外側にする。ループ回数は100回で済みます。
失敗: 商品マスタを外側にする。ループが10万回走り、システムに大きな負荷がかかります。
4. DB製品ごとの「インデックス」と「ヒント」
以前の記事でも触れましたが、実行計画が思い通りにいかない時の対処法をおさらいします。
Oracle:
/*+ INDEX(テーブル名 インデックス名) */というヒント句で、特定のインデックスを使うよう強制できます。PostgreSQL: ヒント句は標準ではありませんが、統計情報を最新にする
ANALYZEコマンドを実行することで、DBに「こっちの表の方が件数が少ないから外側にしよう」と正しく判断させることができます。MySQL:
STRAIGHT_JOINという構文を使うと、FROM句に書いた順番通りに結合(左側を外側にする)を強制できます。
5. 見習いエンジニアの考察:理論がトラブルを救う
現場で「画面の表示が遅い!」と呼び出されたとき、真っ先に確認するのはこの**「インデックスのない入れ子ループ」**が発生していないかです。
SQLの書き方は間違っていなくても、データの増大や統計情報のズレによって、DBが最適な道を見失うことがあります。そんな時、今回学んだ「内側のインデックス」や「駆動表の選択」という理論を知っていれば、冷静に原因を突き止め、解決策(インデックス作成や統計更新)を提示できます。
試験勉強で得た知識が、現場のトラブルを解決する「最強の武器」に変わる瞬間です。