MySQLのEXPLAIN(実行計画)の読み方を完全解説!データベースの検索スピードを劇的に速くする方法
生徒
「データベースからデータを取り出すとき、なんだか時間がかかることがあるんです。パソコンの中で何が起きているんでしょうか?」
先生
「それは、データベースがデータを探すときに、とても遠回りをしているからかもしれません。実はMySQLには、自分がどうやってデータを探しに行くか教えてくれる機能があるんですよ。」
生徒
「えっ、中身が見えるんですか? でも、難しそうですね…。」
先生
「『EXPLAIN(エクスプレイン)』という魔法の言葉を使うだけです。図書室で本を探すときに、闇雲に全部の棚を見るのか、目次を見て最短距離で進むのか、その作戦会議の結果を覗き見するようなものですよ。」
1. MySQLの「実行計画」とは?
データベースを操作する言葉、SQLを使って「このデータをちょうだい!」と命令を出したとき、MySQLというシステムは裏側で「どうすれば一番早くデータを見つけられるか」を一生懸命考えます。この「探し方の手順書」のことを、専門用語で「実行計画(じっこうけいかく)」と呼びます。
例えば、10,000ページある電話帳から「山田さん」を探すとしましょう。1ページ目から順番にめくって探すのは大変ですよね? 索引(あいうえお順のインデックス)を使ってパッと開けば一瞬です。データベースも同じように、効率の良い探し方を知っているかどうかが、アプリやWebサイトの「サクサク感」に直結します。
2. EXPLAINの基本!どうやって使うの?
MySQLに対して「あなた、どうやってそのデータを探すつもり?」と聞き出すには、普段使っている SELECT 文の先頭に EXPLAIN と付けるだけです。これで、実際にデータを検索するのではなく、その検索の「やり方」を画面に表示してくれます。
まずは、今回使う「ユーザー名簿(usersテーブル)」の中身を見てみましょう。会員さんの情報が入っている表です。
id | name | age | city | status
---+----------+-----+-----------+---------
1 | 山田太郎 | 25 | 東京都 | active
2 | 佐藤花子 | 19 | 大阪府 | inactive
3 | 鈴木一郎 | 30 | 神奈川県 | active
4 | 田中次郎 | 45 | 東京都 | active
5 | 伊藤美紀 | 22 | 福岡県 | active
6 | 渡辺健太 | 33 | 北海道 | active
7 | 中村七海 | 28 | 愛知県 | inactive
8 | 小林直樹 | 31 | 東京都 | active
この名簿から、「東京都に住んでいる人」を探す命令を考えてみます。普通に書くとこうなりますね。
SELECT * FROM users WHERE city = '東京都';
これの頭に EXPLAIN を付けて実行してみましょう。これが「作戦会議の結果」を表示させる魔法です。
EXPLAIN SELECT * FROM users WHERE city = '東京都';
3. EXPLAINの結果を読み解くポイント
実行すると、表のような形式でたくさんの情報が出てきます。初心者の方がまず見るべきポイントは、たったの3つだけです。「type(タイプ)」「rows(ローズ)」「Extra(エキストラ)」に注目してください。
id | select_type | table | type | possible_keys | key | rows | Extra
---+-------------+-------+------+---------------+------+------+-------------
1 | SIMPLE | users | ALL | NULL | NULL | 8 | Using where
この結果の重要な部分を解説します。
- type (タイプ): データへのアクセスの種類です。ここが ALL になっていると、要注意です!「全件スキャン」といって、最初から最後まで全部のデータを見ている状態です。データが100万件あったら100万回探すので、とても遅くなります。
- rows (ローズ): 「だいたい何件のデータを調べる必要があるか」の予測数です。ここが大きな数字になっているほど、検索に時間がかかっています。
- Extra (エキストラ): 追加情報です。
Using filesortやUsing temporaryと出ているときは、処理が重たくなっているサインです。
4. 劇的に速くなる!「インデックス」を使った場合
先ほどの ALL(全件スキャン)を改善するために、「インデックス(Index)」というものを作ってみます。インデックスは、辞書の「爪(見出し)」のようなもので、特定の項目をすぐに探せるようにする仕組みです。今回は city(住所)にインデックスを作ったと仮定して、もう一度 EXPLAIN を実行してみます。
-- city列にインデックス(目次)を貼った後の検索
EXPLAIN SELECT * FROM users WHERE city = '東京都';
すると、結果は次のように変わります。
id | select_type | table | type | possible_keys | key | rows | Extra
---+-------------+-------+------+---------------+----------+------+-------
1 | SIMPLE | users | ref | city_index | city_index | 3 | NULL
ここが注目ポイントです!
- typeが「ref」に変化:
ALLではなくなりました!これは、インデックスを使って効率よく探せている証拠です。 - rowsが「3」に減少: もともとは全件の 8 を調べていましたが、インデックスのおかげで「東京都の人は3人だな」と、必要な場所だけを見に行くようになったため、調べる回数が劇的に減りました。
このように、EXPLAIN を見ることで、「インデックスがちゃんと効いているかな?」「無駄な探し方をしていないかな?」ということが一目でわかるようになります。
5. これが出たら危険!「最速」と「最遅」の見分け方
データベースのパフォーマンスを改善する「チューニング」において、type の値は成績表のようなものです。以下の表で、自分が実行した SQL がどのくらいの成績かチェックしてみましょう。
| 評価 | typeの値 | 意味と対策 |
|---|---|---|
| 悪い | ALL | 全てのデータを上から下まで全部見ています。データが増えると激重になります。 |
| 普通 | index | インデックスを端から端まで全部見ています。ALLよりはマシですが、まだ遅いです。 |
| 良い | range | 「10歳から20歳まで」のように、範囲を絞って探せています。 |
| 最高 | const / eq_ref | 「ID番号が5番の人」のように、ピンポイントで1件を特定できています。世界最速です。 |
6. 実際の改善例:複雑な検索を覗いてみる
今度はもう少し複雑な例を見てみましょう。「ステータスが有効(active)で、かつ30歳以上の人」を探す場合です。まずは対象のデータを確認します。
id | name | age | city | status
---+----------+-----+-----------+---------
3 | 鈴木一郎 | 30 | 神奈川県 | active
4 | 田中次郎 | 45 | 東京都 | active
6 | 渡辺健太 | 33 | 北海道 | active
8 | 小林直樹 | 31 | 東京都 | active
この検索を EXPLAIN で確認してみます。
EXPLAIN SELECT * FROM users WHERE status = 'active' AND age >= 30;
実行結果の Extra 欄に Using where とだけ出ている場合は、データベースが条件を一つずつ判定している状態です。もしここに Using index condition と出ていれば、データベースの目次機能をフル活用して、中身の表をめくる前に「誰が対象か」をかなり絞り込めているという意味になります。これこそが、サクサク動くシステムを作るコツなのです。
難しい言葉に感じるかもしれませんが、EXPLAIN は「データベース君との対話」です。「今はこうやって探しているよ」「次はこうしてみて」というやり取りをすることで、どんなに膨大なデータでも一瞬で取り出せる魔法のようなスキルが身につきます。まずは、自分が書いた SELECT の前に EXPLAIN を付ける癖をつけて、type が ALL になっていないかチェックするところから始めてみましょう。