SQLクエリはどう実行される?データベースの裏側を図解


SQLクエリ実行の流れ SQL文 SELECT ... パーサー 文法チェック オプティマイザ 最適な計画を選択 実行エンジン データ取得 結果 行データ バッファプール(メモリ) キャッシュ 統計情報 高速アクセス ⚡ ストレージ(ディスク) テーブル インデックス 永続化データ 💾
SQLクエリ実行の流れ
ひよこ ひよこ

SQLでSELECTって書くと結果が返ってくるけど、中で何が起きてるの?

ペンギン先生 ペンギン先生

実は裏側では5つのステップを踏んでいるんだよ。まず「パーサー」がSQL文を読んで文法チェックをする。人間でいうと「この日本語、文法的に合ってるかな?」と確認する段階だね。

ひよこ ひよこ

文法チェックの次は何をするの?

ペンギン先生 ペンギン先生

次は「オプティマイザ」の出番。これがデータベースの頭脳とも言える部分で、「どの順番でテーブルを読むか」「インデックスを使うかフルスキャンするか」を判断するんだ。同じ結果を返すにも何通りもの方法があって、その中から最速の方法を選ぶんだよ。

ひよこ ひよこ

へぇ〜!最速の方法ってどうやって決めるの?

ペンギン先生 ペンギン先生

テーブルの行数やインデックスの種類、データの偏りなど「統計情報」を使って判断するんだ。たとえば100万行のテーブルから1件探すなら、全行スキャンよりB-Treeインデックスを使ったほうが速い、みたいな計算をしているよ。

ひよこ ひよこ

それで実際にデータを取りに行くの?

ペンギン先生 ペンギン先生

そう!オプティマイザが作った「実行計画」に従って「実行エンジン」がストレージからデータを読み出す。ディスクから読むと遅いから、よく使うデータは「バッファプール」というメモリ上のキャッシュに置いてあるんだ。

ひよこ ひよこ

JOINとかWHEREが複雑だと遅くなるのはなぜ?

ペンギン先生 ペンギン先生

JOINは複数のテーブルを組み合わせる処理だから、組み合わせ方次第で計算量が爆発するんだ。たとえばテーブルA(1万行)×テーブルB(1万行)を単純に全組み合わせすると1億回の比較になる。だからインデックスJOINアルゴリズムの選択が重要なんだよ。

ひよこ ひよこ

実行計画って確認できるの?

ペンギン先生 ペンギン先生

EXPLAINコマンドを使えば見られるよ。「EXPLAIN SELECT ...」と書くだけで、オプティマイザがどんな計画を立てたか表示される。遅いクエリのチューニングでは必須のテクニックだね。

ひよこ ひよこ

プロのエンジニアはどうやってクエリを速くしてるの?

ペンギン先生 ペンギン先生

まずEXPLAIN実行計画を見て、フルスキャンしている箇所にインデックスを追加するのが基本。あとは「必要なカラムだけSELECTする」「サブクエリJOINに書き換える」「LIMIT句で取得件数を制限する」といったテクニックがあるよ。実はオプティマイザも万能じゃなくて、ヒント句で人間が「こっちの方法を使って」と指示することもあるんだ。