MySQL インデックス設計の基本
投稿日:2026/02/04
MySQLを使った開発で、こんな経験はありませんか?
- インデックスを貼ったのにSQLが速くならない
- どのカラムにインデックスを貼るべきか分からない
- とりあえずインデックスを増やしている
インデックスは 正しく設計すれば高速化の武器 になりますが、
間違えると逆にパフォーマンスを悪化 させます。
本記事では、実務で使えるインデックス設計の基本ルール を解説します。
インデックスとは?
インデックスは、本の索引(目次) のようなものです。
- インデックスなし:全ページを最初から探す
- インデックスあり:目的のページに一瞬でジャンプ
CREATE INDEX idx_users_email ON users(email);
これにより、email での検索が高速になります。
なぜインデックス設計が重要なのか?
インデックスがない、または設計が悪いと、
- フルテーブルスキャン(type: ALL)
- レスポンス悪化
- 本番障害の原因
になります。
👉 SQLチューニング = インデックス設計 と言っても過言ではありません。
インデックスを貼るべきカラム
① WHERE句でよく使われるカラム
SELECT * FROM users WHERE email = 'test@example.com';
👉 email にインデックスは 必須候補
② JOINで使われるカラム
SELECT *
FROM posts
JOIN users ON posts.user_id = users.id;
👉 posts.user_id にインデックスを貼る
③ ORDER BY / GROUP BY で使われるカラム
SELECT * FROM posts
ORDER BY created_at DESC;
👉 created_at にインデックス検討
インデックスを貼らなくていいカラム
❌ データ件数が少ない
- 数十件〜数百件のテーブル
- フルスキャンでも十分速い
❌ 更新頻度が極端に高い
- ステータスフラグ
- カウンタ系
👉 UPDATE/INSERTが遅くなる原因に
❌ 値の種類が少ない(低カーディナリティ)
status: 0 / 1
gender: male / female
👉 効果が出にくい
単一カラムインデックス vs 複合インデックス
単一カラムインデックス
CREATE INDEX idx_posts_user_id ON posts(user_id);
- 単純
- 判断しやすい
複合インデックス
CREATE INDEX idx_posts_user_created
ON posts(user_id, created_at);
👉 左から順番に使われる(最重要)
複合インデックスの注意点(左端一致)
(user_id, created_at)
| SQL | インデックス |
|---|---|
| WHERE user_id = 1 | ✅ |
| WHERE user_id = 1 AND created_at > now() | ✅ |
| WHERE created_at > now() | ❌ |
SELECT * はインデックスを殺す
SELECT * FROM users WHERE email = 'test@example.com';
👇 改善
SELECT id, email FROM users WHERE email = 'test@example.com';
👉 カバリングインデックス が使える可能性あり
カバリングインデックスとは?
CREATE INDEX idx_users_email_name ON users(email, name);
SELECT email, name FROM users WHERE email = 'test@example.com';
- データ本体を読まない
- 高速
EXPLAINで Using index が表示される。
EXPLAINで必ず確認する
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
チェックポイント:
- type が
ALLになっていないか - key が NULL ではないか
- rows が多すぎないか
よくあるNGインデックス設計
❌ とりあえず全部貼る
- インデックス肥大化
- INSERT / UPDATE が遅くなる
❌ .envやconfigで管理しようとする
👉 インデックスは DB設計の責務
❌ 実行計画を見ない
👉 EXPLAINなしのインデックス設計は博打
インデックス追加の基本手順
- 遅いSQLを特定
- EXPLAINを確認
- WHERE / JOIN / ORDER BY を確認
- 必要最小限のインデックスを追加
- 再度EXPLAINで確認
Laravel開発での注意点
- Eloquentの裏はSQL
- migrationでインデックスを明示する
$table->index('user_id');
まとめ
インデックス設計で大切なのは、
- 使われるSQLを基準に考える
- 貼りすぎない
- 必ずEXPLAINで確認する
ことです。
まずは、
- WHERE
- JOIN
- ORDER BY
この3つから見直すだけで、 SQLのパフォーマンスは大きく改善 します。