MySQLのEXPLAINの見方を徹底解説!出力の読み方・最適化のコツ・実践例も紹介

目次

1. MySQL EXPLAINとは?なぜ使うべきか

EXPLAINとは?実行計画を可視化するコマンド

MySQLにおけるEXPLAIN(エクスプレイン)は、SQLクエリがどのように実行されるかを可視化するためのコマンドです。特にSELECT文などでデータの取得方法を把握する際に用いられ、クエリの実行計画(execution plan)を表示する役割を果たします。

たとえば、あるテーブルに対してSELECT * FROM users WHERE age > 30といったクエリを実行したとき、MySQLが内部で「どのインデックスを使っているのか」「どの順番でテーブルを走査しているのか」といった情報をEXPLAINを通じて知ることができます。

使い方はシンプルで、クエリの頭に EXPLAIN を付けるだけです。

EXPLAIN SELECT * FROM users WHERE age > 30;

このように記述すると、クエリの実行計画に関する複数のカラムが表示されます。それぞれの項目は、後のセクションで詳しく解説していきます。

知らないと損!クエリが遅い原因が「見える化」される

多くの開発者が陥りがちなのが、「動くSQLだから問題ない」と思ってしまうことです。しかし、実際にはクエリの実行速度が遅いことが、アプリケーションのパフォーマンス全体に悪影響を及ぼすことがあります。

特に大量データを扱うサービスでは、1つの非効率なクエリがボトルネックとなり、サーバーに大きな負荷をかけてしまうケースも少なくありません。

そんなときに役立つのがEXPLAINです。実行計画を確認することで、どのテーブルが全件スキャン(フルテーブルスキャン)されているのか、インデックスが適切に使われているのか、といった情報が「見える化」されます。

つまり、EXPLAINを使うことで、パフォーマンスが悪い原因を特定し、改善の方向性を判断できるのです。特にインデックスの効き具合は、EXPLAINを見ることで明確にわかるようになります。

EXPLAINで対応できるステートメント一覧(SELECT/UPDATEなど)

EXPLAINは、SELECT文だけでなく、以下のような他のSQL文にも対応しています。

  • SELECT
  • DELETE
  • INSERT
  • REPLACE
  • UPDATE

たとえば、大量データに対してDELETE文を実行する場合、インデックスが効いていなければ全件削除処理が実行され、処理時間が大幅に伸びることもあります。こうした状況を未然に防ぐためにも、DELETEやUPDATEの前にEXPLAINで実行計画を確認することは非常に有効です。

なお、MySQLバージョンによってはEXPLAIN ANALYZEというさらに詳細な実行情報を取得できるコマンドも利用可能です。こちらは後半のセクションで補足します。

2. EXPLAINの出力項目の意味と見方【図解イメージ付き】

基本的な出力列の一覧と説明

EXPLAINの出力には、以下のようなカラムが表示されます(MySQLのバージョンによって若干異なる場合があります)。

カラム名説明
idクエリ内での実行順序やグループを示す識別子
select_typeサブクエリやUNIONなど、SELECT文のタイプ
table対象となるテーブル名
typeテーブルの結合方式(アクセス方法)
possible_keys使用可能なインデックス候補
key実際に使用されたインデックス
key_len使用されたインデックスの長さ(バイト単位)
refインデックスと比較される値
rowsMySQLが予測する走査行数
Extraその他の補足情報(ソートや一時テーブル使用など)

これらの中でも、特にtype / key / rows / Extraの4つは、パフォーマンス改善の観点から非常に重要です。

特に重要な4項目「type / key / rows / Extra」の見方

1. type(アクセス方式)

この項目は、クエリがどのような方法でテーブルにアクセスしているかを表します。パフォーマンスに直結する項目です。

値の例意味性能の目安
ALLフルテーブルスキャン✕ 遅い
indexインデックス全体のスキャン
range範囲スキャン
ref / eq_refインデックスを用いた参照
const / system単一行に限定◎(非常に高速)

type = ALL は、インデックスが使われず、すべての行を走査する最も遅いアクセス方式です。refconst を目指してクエリを改善するのが理想です。

2. key(使用されたインデックス)

この項目には、実際に使用されたインデックスの名前が表示されます。
何も表示されていない場合、インデックスが効いていない可能性が高いです。

3. rows(予測される走査行数)

MySQLがクエリの実行時に走査すると予測している行数です。この数値が多ければ多いほど、処理時間が長くなる傾向があります。rows = 1 に近づけるようにクエリを最適化するのが目標です。

4. Extra(補足情報)

Extraには、ソート処理や一時テーブルの使用など、クエリ実行に関する追加情報が表示されます。特に注意すべき項目は以下です。

Extraの例意味対策の目安
Using temporary一時テーブルを使用(パフォーマンス低下)GROUP BYやORDER BYの見直し
Using filesortソート処理が手動で行われているインデックスによるソートの導入
Using indexインデックスのみでデータを取得(高速)○ むしろ良い状態

Using temporaryUsing filesortがある場合は、SQL文やインデックスの設計を見直す必要があります。

【図解イメージ】EXPLAIN結果のサンプル(例)

EXPLAIN SELECT * FROM users WHERE age > 30;
idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEusersALLage_indexNULLNULLNULL5000Using where

この例では、インデックス(age_index)はあるものの、実際には使用されておらず、ALL(フルスキャン)になっていることが分かります。改善の余地がある状態です。

3. 実例で学ぶ!EXPLAINの使い方と読み解き方

例1:シンプルなSELECT文のEXPLAIN結果と解説

まずは、単一テーブルに対する簡単なSELECT文を例に見てみましょう。

EXPLAIN SELECT * FROM users WHERE age > 30;

このクエリのEXPLAIN結果が次のようであったとします。

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEusersALLageNULLNULLNULL5000Using where

解説:

  • type: ALL → フルテーブルスキャン。インデックスが使われていない状態。
  • key: NULL → 使用されているインデックスがない。
  • rows: 5000 → 約5000行を走査すると予測されている。

改善策:

age列にインデックスを追加することで、クエリのパフォーマンスを大幅に向上させることができます。

CREATE INDEX idx_age ON users(age);

再びEXPLAINを実行すると、typerangerefになり、インデックスが使用されたことが確認できるでしょう。

例2:JOINを含むクエリの出力を分析してみよう

次に、複数テーブルをJOINする例を見てみましょう。

EXPLAIN
SELECT orders.id, users.name
FROM orders
JOIN users ON orders.user_id = users.id
WHERE users.age > 30;

結果例:

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEusersALLPRIMARY, ageNULLNULLNULL3000Using where
1SIMPLEordersrefuser_iduser_id4users.id5Using index

解説:

  • usersテーブルがフルスキャン(ALL)になっているため、ここを改善すべき。
  • 一方で、ordersテーブルはrefでインデックスが使われており、効率的。

改善ポイント:

  • users.ageにインデックスを追加すれば、usersテーブルのスキャンが高速化できます。
  • JOINする前に、WHERE句でフィルタを効かせられるようにインデックスを設計するのが鍵です。

インデックスが効いていない例と改善方法【悪い例→良い例】

悪い例:関数を使ったWHERE句

SELECT * FROM users WHERE DATE(created_at) = '2024-01-01';

このようなクエリでは、インデックスが無効になります。なぜなら、DATE()関数により列が変形されてしまい、MySQLがインデックスを利用できなくなるためです。

改善例:関数を使わずに範囲で指定する

SELECT * FROM users
WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02';

これでcreated_at列のインデックスが有効になり、効率よくデータを取得できます。

結論:EXPLAINの実例を活用してパフォーマンスを診断しよう

実際にEXPLAINを使って出力を分析することで、クエリのどこにボトルネックがあるのか、どう最適化すべきかが見えてきます。

  • ALL → フルスキャン!インデックスを検討しよう
  • key = NULL → インデックス未使用。要チェック
  • ExtraUsing temporary → パフォーマンス警告
  • 条件に関数や演算を使うと、インデックスは無効に

このような点を意識しながらEXPLAINを活用することで、日常的なクエリ改善が可能になります。

4. EXPLAIN結果から行うクエリ最適化の実践テクニック

「type: ALL」を回避するインデックス設計の基本

EXPLAINで type: ALL と表示された場合、それはフルテーブルスキャンが行われていることを意味します。これは非常に負荷の高い処理であり、数千件〜数百万件のデータがあるテーブルでは大きなボトルネックとなります。

回避するための対策:

  • WHERE句に使用するカラムにインデックスを張る
  CREATE INDEX idx_age ON users(age);
  • 複数の条件がある場合は、複合インデックスを検討
  CREATE INDEX idx_status_created ON orders(status, created_at);
  • 文字列の前方一致以外のLIKEは避ける
  -- 悪い例(インデックス効かない)
  WHERE name LIKE '%tanaka%'

  -- 良い例(インデックス効く可能性あり)
  WHERE name LIKE 'tanaka%'

「Extra: Using temporary」の意味と対処法

Extra列に「Using temporary」と表示された場合、それはMySQLが一時テーブルを内部で生成してクエリを処理していることを意味します。これは通常、GROUP BYORDER BYなどの操作がインデックスだけで処理できず、一時領域を使って手作業でデータを整理しているという状態です。

対処法:

  • GROUP BYやORDER BYに使用するカラムにもインデックスを適用する
  CREATE INDEX idx_group_col ON sales(department_id);
  • 不要なソート処理やGROUP BYをSQLから排除する
  • LIMITやサブクエリを活用して対象データを絞る

「rows」や「key」が示す改善ポイントを把握する

rows列は、MySQLがそのテーブルから何行を読み取る必要があると予測しているかを示しています。例えば、rows = 100000と出るようなクエリでは、パフォーマンスに大きく影響します。

この値が大きいときは、対象となる行数を減らすインデックスの適用や、条件式の見直しが必要です。

一方、key列には実際に使用されたインデックスが表示されます。ここがNULLであれば、インデックスが使われていないという警告です。

改善チェックポイント:

  • rowsが多い → 絞り込み条件が適切か?インデックスは効いているか?
  • key = NULL → WHEREやJOIN句にインデックスが効かない構文を使っていないか?

EXPLAINと最適化のサイクルを習慣化しよう

クエリをチューニングするためには、書いて→EXPLAINで確認→改善して再確認というサイクルを繰り返すのが基本です。

以下のような流れを意識しましょう。

  1. まずは通常通りクエリを書く
  2. EXPLAINで実行計画を確認
  3. type, key, rows, Extraをチェック
  4. ボトルネックがあれば、インデックスや構文を見直す
  5. 再度EXPLAINで改善結果を確認

クエリのパフォーマンスは、インデックスの有無だけでなくクエリの書き方そのものにも大きく影響されます。関数を使わず、シンプルな比較演算子を使うなどの工夫も効果的です。

5. MySQL WorkbenchのVisual EXPLAINを使った可視化分析

GUIツールで視覚的に実行計画をチェック

MySQL Workbenchは、MySQLの管理や開発に特化したGUIツールです。ターミナルの出力では見づらい実行計画も、図解的に可視化してくれるのが大きな特徴です。

Visual EXPLAINを使えば、次のような情報をツリー構造で確認できます:

  • 各テーブルのアクセス順序
  • JOINの種類
  • インデックスの使用状況
  • フルテーブルスキャンの有無
  • データのフィルタリングやソート処理の有無

図で表示されるため、初心者でも視覚的に「どこが重たいのか」を把握しやすくなります。

【画像付き】Visual Explainの見方と使い方(手順)

Visual EXPLAINを使う手順は以下の通りです:

  1. MySQL Workbenchを起動し、接続先のデータベースを開く
    → 接続は事前に設定しておきましょう。
  2. SQLエディタに対象のクエリを入力
SELECT * FROM users WHERE age > 30;
  1. 「EXPLAIN」ボタンの右にある「EXPLAIN VISUAL」アイコンをクリック
    → または右クリックメニューから「Visual Explain」を選択します。
  2. 実行計画がビジュアル表示される
    各ノード(テーブル)をクリックすると、以下のような詳細情報が表示されます:
  • アクセス方法(ALL、ref、rangeなど)
  • 使用インデックス
  • 予測行数(rows)
  • フィルタ条件やJOIN方式

補足:
Visual Explainでは、各ノードの色やアイコンで重い処理や非効率な部分がひと目でわかります。
特に「赤く表示されたノード」はパフォーマンス上の注意点としてチェックしましょう。

初心者でも簡単にボトルネックを見つけられる!

テキストベースのEXPLAINは慣れるまでは読みづらいと感じる方も多いですが、Visual Explainなら視覚的に「悪い箇所」が浮き彫りになります。

たとえば、以下のようなケースに気づきやすくなります:

  • type: ALLが使用されているテーブル
  • Using temporaryが発生しているクエリブロック
  • 不要なJOINが多くなっているパターン
  • インデックスが使われていないテーブルの特定

GUIにより、チューニングポイントの仮説をすばやく立てることができ、チーム内での共有やレビューにも便利です。

Visual EXPLAINは、特にSQL初心者〜中級者にとって非常に心強いツールです。
「EXPLAIN結果をどう見ていいか分からない…」という方は、ぜひこの機能を活用してみてください。

6. よくある質問(FAQ)

Q1. EXPLAINはどんな場面で使うべきですか?

A. クエリの実行速度に不安を感じたとき、特に「なんとなく遅い」と感じるSQLがある場合に使うべきです。また、新しく作成したクエリが適切にインデックスを使っているか確認したい時にも有効です。

実行前にEXPLAINを使って実行計画を確認することで、リリース前にパフォーマンスのリスクを発見できます。

Q2. 出力の「type」がALLになっているけど、どうすれば?

A. type: ALLは、MySQLがテーブル全体をフルスキャンしている状態です。これは非常にコストの高い処理で、特に行数の多いテーブルではパフォーマンスを大きく低下させます。

対策としては以下を検討しましょう:

  • WHERE句に使われているカラムにインデックスを追加する
  • インデックスが効かなくなるような関数や演算を使わない
  • SELECT * を避け、必要なカラムだけを取得する

Q3. Extra列に「Using temporary」とあるが問題?

A. Using temporaryは、MySQLが一時テーブルを内部的に作成してクエリを処理していることを意味します。GROUP BYORDER BYなどが原因で発生しやすく、メモリやディスクI/Oのコストが発生します。

対処法としては:

  • GROUP BY / ORDER BYに使われるカラムにインデックスを張る
  • 不要なソートや集計を避け、アプリ側で処理できないか検討する
  • LIMITやサブクエリを活用して対象データを減らす

Q4. Visual EXPLAINを使うにはどうすればよい?

A. MySQL公式ツール「MySQL Workbench」を使えば、GUI上で簡単にEXPLAIN結果を可視化できます。使い方は簡単で、クエリを入力したあと「Visual Explain」ボタンをクリックするだけです。

特に以下のような方におすすめです:

  • テキストベースのEXPLAIN出力が読みにくいと感じる方
  • JOINや複雑なクエリの構造を視覚的に把握したい方
  • チームでSQLパフォーマンスを共有・議論したいとき

Q5. インデックスがあるのに使われないのはなぜ?

A. インデックスが存在しても、MySQLがそれを使用するとは限りません。以下のようなケースではインデックスが無視されます:

  • WHERE句で関数や演算子を使っている(例:WHERE YEAR(created_at) = 2024
  • カーディナリティ(値のばらつき)が低く、全件スキャンのほうが速いと判断された場合
  • 組み合わせるカラムの順序が複合インデックスと一致していない場合

インデックスが正しく使われているかを確認するには、必ずEXPLAINでkey列を見るようにしましょう。

7. まとめ|EXPLAINを使えばSQLの改善ポイントが見える!

MySQLにおけるパフォーマンスチューニングは、単にインデックスを張るだけでは不十分です。
どのクエリがボトルネックになっているのか、なぜ遅いのか、その原因を明らかにするために欠かせないツールが「EXPLAIN」です。

本記事では、以下のポイントを中心に解説してきました。

✅ EXPLAINの役割と基本的な使い方

  • クエリに EXPLAIN を付けるだけで、実行計画を確認できる
  • フルスキャン(ALL)やUsing temporaryなどの問題点が可視化される

✅ 出力項目の読み方と、パフォーマンスの見極め方

  • type, key, rows, Extra の4項目は特に重要
  • フルスキャンを避け、インデックスが活用されている状態が理想
  • Using temporary や Using filesort が出ている場合は要注意

✅ 実例による診断と最適化の実践方法

  • インデックスの追加だけでなく、SQL構文の工夫も大切
  • JOINやサブクエリを含む複雑なSQLでも、EXPLAINで分解できる
  • 実行計画を分析しながらクエリを「磨く」ことが、パフォーマンス向上の近道

✅ GUIツールを活用して視覚的に確認する方法

  • MySQL Workbenchの「Visual EXPLAIN」で実行計画を図で確認
  • 初心者でも視覚的にボトルネックを発見しやすい
  • SQLパフォーマンスのチーム共有にも便利

✅ FAQで実務の悩みにも対応

  • type=ALLやkey=NULLなどの問題の原因と対処法を整理
  • インデックスが効かない理由も事例付きで解説

✍️ EXPLAINを“習慣化”すれば、SQL力は大きく成長する

SQLを書くたびにEXPLAINでチェックする癖をつけておけば、無意識に「速いクエリ」を書けるようになります。それは単なるテクニックではなく、プロとしての「SQLリテラシー」の土台です。

  • 書いたらすぐEXPLAIN
  • おかしな実行計画があればすぐ直す
  • 効率のよいインデックス設計を考える

このサイクルを身につけることで、あなたのMySQLスキルは確実にレベルアップしていきます。

本記事が、あなたのクエリ最適化の第一歩となれば幸いです。
ご質問や補足してほしい内容があれば、コメント等でお気軽にお知らせください!