Instiq
第5章 · 性能設計とチューニング·v1.0.0·更新 2026/7/10·読了目安 約17分

変更要約: 初版

5.2実行計画とオプティマイザ

この節の要点

DBMSが問合せの実行方法を自動で選ぶコストベース最適化の仕組み、その判断材料となる統計情報、複数テーブルの結合方式ネステッドループ結合ソートマージ結合ハッシュ結合)の使い分け、そして全表走査インデックススキャンのどちらが有利かを見極める判断を学びます。

アプリケーション開発者やDBAにとって、SQL文そのものが正しくても実行が遅い場合、原因はDBMSがどの手順(実行計画)でその問合せを処理しているかにあります。この節では、DBMSが「どの実行計画が最も速いか」を推定する仕組みであるオプティマイザの考え方と、実行計画を読み解いて遅いクエリを改善する判断力を学びます。

5.2.1コストベース最適化と統計情報

  • コストベース最適化(CBO:Cost-Based Optimization)=同じ結果を得られる複数の実行計画候補(どのインデックスを使うか・どの結合方式にするか等)について、それぞれのI/O・CPUコストを見積もり、推定コストが最小の計画を選ぶ方式。現代の主要なRDBMSはこの方式を採用している。
  • コスト見積もりの精度は統計情報(列ごとの値の分布・行数・NULL率・インデックスの選択性等をDBMSが収集したメタデータ)の鮮度に大きく依存する。大量の一括更新・削除の直後など統計情報が古いままだと、実際とかけ離れた行数を見積もり、不適切な実行計画(本来インデックスを使うべき所で全表走査を選ぶ等)を選んでしまうリスクがある。統計情報の再収集(ANALYZE等)を運用に組み込むことが重要になる。

5.2.2結合方式(ネステッドループ/ソートマージ/ハッシュ結合)

  • ネステッドループ結合=外側のテーブルの各行に対して、内側のテーブルを繰り返し検索して一致行を探す方式。内側テーブルの結合列にインデックスがあれば非常に高速だが、インデックスがなければ内側テーブルを行数分繰り返し全表走査することになり、両テーブルが大きいと極めて遅くなる。外側テーブルの行数が少ない場合に向く。
  • ソートマージ結合=両テーブルを結合列であらかじめソートしたうえで、ソート済みの2つの列を先頭から同時に走査してつき合わせる方式。ソート自体にコストがかかるが、既にソート済み(インデックス経由等)であれば効率的。ハッシュ結合=小さい方のテーブルの結合列からハッシュテーブルを構築し、大きい方のテーブルの各行についてハッシュテーブルを参照して一致を探す方式。等価結合(=)に強く、大量データ同士の結合でインデックスが使えない場合でも比較的高速だが、ハッシュテーブル構築にメモリを要する。
試験ポイント

「ネステッドループ=内側にインデックスがあれば速いが大量データ同士は苦手」「ソートマージ=事前ソート済みなら効率的」「ハッシュ結合=等価結合で大量データに強いがメモリを要する」が最頻出です。オプティマイザの判断は統計情報の鮮度次第で狂うことも押さえましょう。

あるDBAが、深夜バッチで実行されるSELECT * FROM orders o JOIN customers c ON o.customer_id = c.customer_id WHERE o.order_date >= '2026-07-01'というクエリが、先月まで数秒で終わっていたのに今月から数分かかるようになった、という報告を受けたとします。実行計画を確認すると、orders側の結合方式がネステッドループ結合から全表走査を伴うネステッドループに変わっており、想定より大幅に遅くなっていました。原因を切り分けるため、まず統計情報の鮮度を疑いました。確認すると、直近でordersテーブルに対して大量の過去データ移行(数百万行のINSERT)が行われた直後で、統計情報が更新されないままになっていました。オプティマイザは古い統計情報(移行前の少ない行数)をもとに「orders側は行数が少ないので、内側テーブルへの繰り返し検索でも十分速い」と誤って見積もり、実際には大幅に増えた行数に対してネステッドループを選んでしまったのです。対処として、まずANALYZE(統計情報の再収集)を実行し、オプティマイザに最新の行数・分布を認識させました。その結果、オプティマイザはハッシュ結合ordersの行数が多く、customer_idでの等価結合が中心のため)を選ぶよう計画を切り替え、実行時間は数秒台に戻りました。この事例が示すのは、SQL文自体や結合条件を変更しなくても、統計情報の陳腐化だけで実行計画が悪化し性能が劣化しうるということであり、DBAは「遅くなった=インデックスが足りない」と即断せず、まず実行計画と統計情報の鮮度を確認してから対処法(統計再収集・インデックス追加・結合方式のヒント指定等)を選ぶ判断が必要です。

結合方式得意な状況弱点/注意点
ネステッドループ結合外側テーブルの行数が少なく内側にインデックスあり内側にインデックスがないと両大テーブルで極めて遅い
ソートマージ結合結合列が既にソート済み未ソートならソート自体のコストが大きい
ハッシュ結合等価結合で大量データ同士ハッシュテーブル構築にメモリを要する
注意

ひっかけ: 「実行計画が遅くなったら原因は必ずインデックス不足である」は誤りです——統計情報が陳腐化しているだけで、インデックスを変更しなくても実行計画は悪化しえます。また「全表走査は常にインデックススキャンより遅い」も誤り=対象行の割合が高い(低選択性の条件)場合は、インデックス経由でランダムアクセスを繰り返すより全表を順に読む方が速いことがあるため、オプティマイザは行数の割合次第で全表走査を合理的に選ぶことがあります。

コストベース最適化・結合方式の図。
DBの選ぶ実行手順

5.2.3この節のまとめ

  • コストベース最適化はI/O・CPUコストが最小の実行計画を選ぶ。判断材料の統計情報が陳腐化すると誤った計画を選びうる
  • ネステッドループ結合(内側にインデックス向き)・ソートマージ結合(事前ソート向き)・ハッシュ結合(大量データの等価結合向き)を使い分ける
  • 全表走査は常に不利とは限らず、対象行の割合が高い(低選択性)場合はインデックススキャンより速いことがある

進捗の記録にはログインが必要です。

理解度チェック

(軽い確認用)

Q1. 深夜バッチのJOINクエリが先月まで数秒で終わっていたのに今月から数分かかるようになった。SQL文・結合条件・インデックス構成には一切変更がなく、直近でorders側テーブルに大量データ移行(数百万行INSERT)があったことが判明した。最初に確認すべきこととして最も妥当なものはどれか。

Q2. 2つの大きなテーブルを`customer_id`の等価条件で結合するクエリがあり、customer_id列にはどちらのテーブルにもインデックスがない。この状況で比較的高速な結合を実現する方式として最も適切なものはどれか。

Q3. ある問合せの条件に一致する行が全体の80%を占めることが分かっている。この列にはインデックスが存在する。オプティマイザが全表走査を選んだ場合の判断として最も妥当な説明はどれか。

理解度を確認第5章「性能設計とチューニング」の問題を解く

学習の記録を残しませんか

参考書はすべて無料で読めます。無料登録すると、問題集での演習・既読と進捗の記録・間違えた問題の復習・ハイライトが使えます。