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 インデックスと比較される値 rows MySQLが予測する走査行数 Extra その他の補足情報(ソートや一時テーブル使用など)
これらの中でも、特にtype / key / rows / Extra の4つは、パフォーマンス改善の観点から非常に重要です。特に重要な4項目「type / key / rows / Extra」の見方 1. type(アクセス方式) この項目は、クエリがどのような方法でテーブルにアクセスしているかを表します。パフォーマンスに直結する項目です。値の例 意味 性能の目安 ALL フルテーブルスキャン ✕ 遅い index インデックス全体のスキャン △ range 範囲スキャン ○ ref / eq_ref インデックスを用いた参照 ◎ const / system 単一行に限定 ◎(非常に高速)
type = ALL は、インデックスが使われず、すべての行を走査する最も遅いアクセス方式です。ref や const を目指してクエリを改善するのが理想です。 2. key(使用されたインデックス) この項目には、実際に使用されたインデックスの名前が表示されます。
何も表示されていない場合、インデックスが効いていない可能性が高いです。 3. rows(予測される走査行数) MySQLがクエリの実行時に走査すると予測している行数です。この数値が多ければ多いほど、処理時間が長くなる傾向があります。rows = 1 に近づけるようにクエリを最適化するのが目標です。 4. Extra(補足情報) Extraには、ソート処理や一時テーブルの使用など、クエリ実行に関する追加情報が表示されます。特に注意すべき項目は以下です。Extraの例 意味 対策の目安 Using temporary 一時テーブルを使用(パフォーマンス低下) GROUP BYやORDER BYの見直し Using filesort ソート処理が手動で行われている インデックスによるソートの導入 Using index インデックスのみでデータを取得(高速) ○ むしろ良い状態
Using temporaryやUsing filesortがある場合は、SQL文やインデックスの設計を見直す必要があります。【図解イメージ】EXPLAIN結果のサンプル(例) EXPLAIN SELECT * FROM users WHERE age > 30;id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE users ALL age_index NULL NULL NULL 5000 Using where
この例では、インデックス(age_index)はあるものの、実際には使用されておらず、ALL(フルスキャン)になっていることが分かります。改善の余地がある状態です。
3. 実例で学ぶ!EXPLAINの使い方と読み解き方 例1:シンプルなSELECT文のEXPLAIN結果と解説 まずは、単一テーブルに対する簡単なSELECT文を例に見てみましょう。EXPLAIN SELECT * FROM users WHERE age > 30; このクエリのEXPLAIN結果が次のようであったとします。id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE users ALL age NULL NULL NULL 5000 Using where
解説: type: ALL → フルテーブルスキャン。インデックスが使われていない状態。key: NULL → 使用されているインデックスがない。rows: 5000 → 約5000行を走査すると予測されている。 改善策: age列にインデックスを追加することで、クエリのパフォーマンスを大幅に向上させることができます。CREATE INDEX idx_age ON users(age); 再びEXPLAINを実行すると、typeがrangeやrefになり、インデックスが使用されたことが確認できるでしょう。例2:JOINを含むクエリの出力を分析してみよう 次に、複数テーブルをJOINする例を見てみましょう。EXPLAIN
SELECT orders.id, users.name
FROM orders
JOIN users ON orders.user_id = users.id
WHERE users.age > 30; 結果例:id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE users ALL PRIMARY, age NULL NULL NULL 3000 Using where 1 SIMPLE orders ref user_id user_id 4 users.id 5 Using 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 → インデックス未使用。要チェックExtraにUsing temporary → パフォーマンス警告条件に関数や演算を使うと、インデックスは無効に このような点を意識しながらEXPLAINを活用することで、日常的なクエリ改善が可能になります。
4. EXPLAIN結果から行うクエリ最適化の実践テクニック 「type: ALL」を回避するインデックス設計の基本 EXPLAINで type: ALL と表示された場合、それはフルテーブルスキャンが行われていることを意味します。これは非常に負荷の高い処理であり、数千件〜数百万件のデータがあるテーブルでは大きなボトルネックとなります。 回避するための対策: CREATE INDEX idx_age ON users(age); CREATE INDEX idx_status_created ON orders(status, created_at); -- 悪い例(インデックス効かない)
WHERE name LIKE '%tanaka%'
-- 良い例(インデックス効く可能性あり)
WHERE name LIKE 'tanaka%'「Extra: Using temporary」の意味と対処法 Extra列に「Using temporary」と表示された場合、それはMySQLが一時テーブルを内部で生成してクエリを処理している ことを意味します。これは通常、GROUP BYやORDER 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で確認→改善して再確認 というサイクルを繰り返すのが基本です。 以下のような流れを意識しましょう。まずは通常通りクエリを書く EXPLAINで実行計画を確認type, key, rows, Extraをチェックボトルネックがあれば、インデックスや構文を見直す 再度EXPLAINで改善結果を確認 クエリのパフォーマンスは、インデックスの有無だけでなくクエリの書き方そのもの にも大きく影響されます。関数を使わず、シンプルな比較演算子を使うなどの工夫も効果的です。
5. MySQL WorkbenchのVisual EXPLAINを使った可視化分析 GUIツールで視覚的に実行計画をチェック MySQL Workbenchは、MySQLの管理や開発に特化したGUIツールです。ターミナルの出力では見づらい実行計画も、図解的に可視化してくれる のが大きな特徴です。 Visual EXPLAINを使えば、次のような情報をツリー構造 で確認できます:各テーブルのアクセス順序 JOINの種類 インデックスの使用状況 フルテーブルスキャンの有無 データのフィルタリングやソート処理の有無 図で表示されるため、初心者でも視覚的に「どこが重たいのか」を把握しやすくなります。【画像付き】Visual Explainの見方と使い方(手順) Visual EXPLAINを使う手順は以下の通りです: MySQL Workbenchを起動し、接続先のデータベースを開く → 接続は事前に設定しておきましょう。SQLエディタに対象のクエリを入力 SELECT * FROM users WHERE age > 30;「EXPLAIN」ボタンの右にある「EXPLAIN VISUAL」アイコンをクリック → または右クリックメニューから「Visual Explain」を選択します。実行計画がビジュアル表示される 各ノード(テーブル)をクリックすると、以下のような詳細情報が表示されます:アクセス方法(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 BY やORDER 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スキルは確実にレベルアップしていきます。 本記事が、あなたのクエリ最適化の第一歩となれば幸いです。
ご質問や補足してほしい内容があれば、コメント等でお気軽にお知らせください!