コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
EXPLAIN の読み方
EXPLAIN の読み方
このレッスンで分かること
- MySQL の EXPLAIN の主要 6 列の意味
- PostgreSQL の EXPLAIN ANALYZE の読み方
- 「遅さの正体」を実行計画から見抜く手順
EXPLAIN の読み方 とは
MySQL / PostgreSQL の実行計画出力を実例で読み解く。本レッスンでは、EXPLAIN の読み方 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
MySQL の type 列 (アクセス方式) 完全早見表
| type | 意味 | 良し悪し | 典型シーン |
|---|---|---|---|
| system | 1 行のテーブル | 最良 | システムテーブル |
| const | PRIMARY/UNIQUE で 1 行確定 | 最良 | WHERE id = 5 |
| eq_ref | JOIN で内側 1 行確定 | 最良 | PK で JOIN |
| ref | インデックスで複数行 | 良 | 普通のインデックススキャン |
| range | 範囲スキャン | 良 | WHERE x BETWEEN ... |
| index | 全インデックススキャン | 注意 | カバリングなら OK |
| ALL | 全表走査 | 危険 | インデックス未使用 = 設計ミス疑い |
Extra 列で要注意のシグナル
| Extra | 意味 | 対策 |
|---|---|---|
| Using index | カバリングインデックス | そのまま (理想) |
| Using where | 追加フィルタ | 多くの行を絞っていれば許容 |
| Using filesort | メモリ/一時ファイルでソート | 複合インデックスにソート列を含める |
| Using temporary | 中間テーブル作成 | GROUP BY 設計を見直す |
EXPLAIN の基本
EXPLAIN は SQL に付けるだけで「DBMS がどう実行する計画か」を表示してくれます。EXPLAIN ANALYZE (PostgreSQL) や EXPLAIN FORMAT=JSON (MySQL) で更に詳しい情報も取れます。
MySQL EXPLAIN の主要列
SQL クエリ
EXPLAIN SELECT u.name, o.amount
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.country = 'JP' AND o.status = 'paid';| id | select_type | table | type | possible_keys | key | rows | Extra |
|---|---|---|---|---|---|---|---|
| 1 | SIMPLE | u | ref | idx_country | idx_country | 1000 | Using where |
| 1 | SIMPLE | o | ref | idx_user,idx_status | idx_user | 8 | Using where |
主要 6 列の意味は次の通りです。
id — クエリ内の SELECT 番号。サブクエリや UNION では複数の id が出る。
select_type — SIMPLE、SUBQUERY、UNION、DERIVED などのクエリの種類。
table — 対象テーブル。
type — 最重要列。アクセス方式。良い順に system > const > eq_ref > ref > range > index > ALL。ALL は全表走査で、これが出たら危険信号。
key — 実際に使われたインデックス。NULL なら未使用。possible_keys には候補が出るが、実際選ばれたのは key の方。
rows — 読まれる推定行数。少ないほど良い。実際の行数とずれていたら統計情報が古い。
Extra — Using index (カバリング)、Using where (フィルタ)、Using filesort (メモリ/一時ファイルでソート)、Using temporary (中間テーブル作成) など。Using filesort や Using temporary が出ているクエリは要注意。
type 列の見方
実務では ref か range が出れば合格、ALL が出たら設計ミスを疑います。
PostgreSQL の EXPLAIN
PostgreSQL は形式が違います。EXPLAIN だけでも見れますが、実行時間も知りたいなら EXPLAIN ANALYZE を使います(実際にクエリが走るので注意)。
プレーンテキスト
EXPLAIN ANALYZE SELECT u.name, o.amount
FROM users u JOIN orders o ON u.id = o.user_id
WHERE u.country = 'JP' AND o.status = 'paid';
Nested Loop (cost=0.85..1234.56 rows=80 width=64) (actual time=0.123..15.456 rows=72 loops=1)
-> Index Scan using idx_country on users u (cost=0.42..345.67 rows=10 width=32) (actual time=0.045..1.234 rows=10 loops=1)
Index Cond: (country = 'JP'::text)
-> Index Scan using idx_user_status on orders o (cost=0.43..88.78 rows=8 width=32) (actual time=0.012..1.345 rows=7 loops=10)
Index Cond: (user_id = u.id)
Filter: (status = 'paid'::text)
Planning Time: 0.234 ms
Execution Time: 16.789 msポイントを読み解きます。
- cost=0.85..1234.56 — 開始コストと総コスト。プランナの推定値
- rows=80 — 推定行数。actual rows=72 が実測値。乖離が大きいと統計が古い
- actual time=... — 実測時間。最初の数字が「最初の行を返すまで」、2 つ目が「最後の行まで」
- loops=10 — 内側の Index Scan が 10 回実行された(外側 10 行 × Nested Loop)
Nested Loop、Index Scan、Filter、Sort、Hash Join などのノードがツリー状に並びます。下から上に 読みます。
統計情報のズレを見抜く
rows=80 (推定) vs actual rows=8000 (実測) のように 100 倍ズレていたら、統計情報が古いか、複数カラムの相関が無視されています。
対策は次の 2 つです。
ANALYZE table_nameで統計再計算- 複数カラムの相関には
CREATE STATISTICS(PostgreSQL) を使う
EXPLAIN で 推定 vs 実測 がずれていたら、プランナの判断は信用できない。
よく出る問題パターン
1. type=ALL(全表走査)
インデックスを貼っていないか、貼っているが使われていない。WHERE の左辺に関数を使うとインデックスが効きません。
SQL クエリ
-- インデックスが効かない
WHERE LOWER(email) = 'alice@ex.com'
-- 関数インデックスを使うか、データ側を小文字化2. Using filesort
ORDER BY がインデックスでカバーできていない。複合インデックスにソート列を含めると解消します。
3. Using temporary
GROUP BY で中間テーブルを作っている。インデックス順と一致しないと発生。
4. rows が極端に多い
絞り込み条件にインデックスが無いか、効きにくい条件。
やってみよう
- 自分のプロジェクトのクエリを 3 つ取り出し、
EXPLAINでtypeを確認する type=ALLが出たクエリにインデックスを貼り、type=refに変わるか確認- PostgreSQL なら
EXPLAIN (ANALYZE, BUFFERS)でディスク I/O も観察する
まとめ
このレッスンの要点は、MySQL 主要 6 列 / PostgreSQL の actual time / 統計情報のズレ検出 の 3 点です。実務でこれらを切り分けて説明できるようになると、設計レビューや障害対応の精度が一段上がります。
理解度チェック
Q. MySQL EXPLAIN の type 列に ALL が出た。最初に疑うべきことは?
- サーバーのスペック不足
- WHERE 句に使うカラムにインデックスがない、または関数で隠されている
- クエリの構文エラー
- TCP コネクション数の上限
答えを見る
正解は 2。type=ALL は全表走査。WHERE 条件にインデックスが効いていない (未作成、または LOWER(col)=... のように関数でインデックスが効かなくなっている) のが典型原因です。
出典 (References)
最終更新: 2026-05-28
関連レッスン
よくある質問
Q. このトピックは実務でどう役立ちますか?
A. DB のクエリ最適化、API 設計、データ構造の選択など、設計判断の根拠になります。表面的にライブラリを使うだけでなく「なぜそれが速いのか」を理解できると、性能問題を未然に防げます。コーディング面接でも頻出のテーマです。
Q. 計算量はどう求めれば良いですか?
A. ループのネストごとに掛け算する、再帰なら漸化式から解く、というのが基本です。Big-O 表記は定数倍と低次の項を無視するため、n の指数(n²、n log n など)に注目してください。最悪・平均・最良の 3 つを意識すると説得力が増します。
Q. 覚えるべき定番アルゴリズムは何ですか?
A. 二分探索、クイックソート/マージソート、BFS/DFS、ダイクストラ、DP の基本問題(フィボナッチ・ナップサック)が必修です。これらを「白紙から書ける」状態にすると、応用問題が一気に解けるようになります。
次のレッスン
次は Nested Loop / Hash / Merge Join で、MySQL / PostgreSQL の実行計画出力を実例で読み解く を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- EXPLAIN の読み方 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. EXPLAIN の読み方 とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン