EXPLAINで見るSQLアンチパターン
投稿日:2026/02/05
本記事では、EXPLAINでよく遭遇するSQLアンチパターン を
実例 → 問題点 → 改善方法 の流れで解説します。
EXPLAINで最低限見るべき項目
まず、以下の項目は必ず確認してください。
| 項目 | 意味 |
|---|---|
| type | アクセス方法(重要) |
| key | 実際に使われたインデックス |
| rows | 走査する想定行数 |
| Extra | 補足情報(Using whereなど) |
👉 type / key / rows が分かれば8割は判断できます。
アンチパターン① type = ALL(フルテーブルスキャン)
EXPLAIN結果
type: ALL
key: NULL
rows: 120000
問題点
- インデックスが使われていない
- テーブル全件走査
- データ増加とともに確実に遅くなる
よくあるSQL
SELECT * FROM users WHERE email = 'test@example.com';
改善方法
CREATE INDEX idx_users_email ON users(email);
改善後:
type: ref
key: idx_users_email
rows: 1
👉 type=ALLは最優先で潰す対象
アンチパターン② key = NULL(インデックスが使われていない)
EXPLAIN結果
type: range
key: NULL
問題点
- インデックスは存在するが使われていない
- SQLの書き方が原因のことが多い
よくある原因① 関数を使っている
SELECT * FROM users
WHERE DATE(created_at) = '2026-02-01';
改善
SELECT * FROM users
WHERE created_at >= '2026-02-01 00:00:00'
AND created_at < '2026-02-02 00:00:00';
👉 インデックスカラムに関数を使うと無効化されやすい
アンチパターン③ rows が異常に多い
EXPLAIN結果
type: ref
rows: 80000
問題点
- インデックスは使われている
- しかし絞り込みが弱い
原因例(低カーディナリティ)
WHERE status = 1
status: 0 / 1
改善方法
CREATE INDEX idx_orders_status_created
ON orders(status, created_at);
👉 複合インデックスで絞り込み精度を上げる
アンチパターン④ 複合インデックスの順番ミス
インデックス
(user_id, created_at)
使われないSQL
WHERE created_at > NOW()
EXPLAIN結果
key: NULL
改善
- インデックス順を見直す
- SQLをインデックスに合わせる
👉 左端一致ルールを守る
アンチパターン⑤ SELECT * による無駄なI/O
EXPLAIN結果
Extra: Using where
問題点
- 必要以上にデータを取得
- インデックスだけで完結できない
改善
SELECT id, email
FROM users
WHERE email = 'test@example.com';
良いEXPLAIN
Extra: Using index
👉 カバリングインデックスが効く
アンチパターン⑥ ORDER BY + filesort
EXPLAIN結果
Extra: Using filesort
問題点
- メモリ or ディスクでソート
- データ量次第で一気に遅くなる
よくあるSQL
SELECT *
FROM posts
ORDER BY created_at DESC;
改善
CREATE INDEX idx_posts_created_at ON posts(created_at);
👉 ORDER BYはインデックスで解決できることが多い
アンチパターン⑦ JOIN先テーブルがALL
EXPLAIN結果(一部)
table: posts
type: ALL
問題点
- JOINキーにインデックスがない
- JOINするたびに全件走査
改善
CREATE INDEX idx_posts_user_id ON posts(user_id);
👉 JOINカラムのインデックスは必須
実務でのEXPLAIN確認フロー
- 遅いSQLを特定
- EXPLAINを実行
- type が ALL か?
- key が使われているか?
- rows が多すぎないか?
- Extra に怪しい表示がないか?
まとめ
- type = ALL
- key = NULL
- rows が多すぎる
- Using filesort
これらを潰すだけでも、 SQLパフォーマンスは大きく改善 します。