章: 第3章: パフォーマンス最適化
データが増えるほど遅くなる——それはインデックス不足のサインです
テスト環境では一瞬だったクエリが、本番の数十万件データでは5秒以上かかる。そういう事態に直面したとき、「インデックスを貼ればいいんじゃないか」と感覚で対応するのは危険です。闇雲にインデックスを追加すると、INSERT/UPDATE のたびにインデックスの更新コストが増え、むしろ書き込みが遅くなる場合もあります。
インデックスは「貼るべき場所に、貼るべき理由をもって」追加するのが正解です。
インデックスの仕組みと、貼るべき場所の判断基準
MySQLのInnoDBはBツリーインデックスを使います。検索時に全行を順番に見る「フルテーブルスキャン」を避け、Bツリーを辿って対象行に直接アクセスするのがインデックスの役割です。
インデックスを貼る場所の基準
| 貼るべき場所 | 効果 | 注意点 |
| WHERE句で頻繁に使うカラム | フルスキャンを回避 | カーディナリティ(値の多様性)が低い列は効果薄 |
| JOIN のON句カラム | 結合速度を大幅改善 | 外部キーには自動でインデックスが付く |
| ORDER BY で使うカラム | ソート処理をスキップ | WHERE + ORDER BY はまとめて複合インデックスに |
| UNIQUE制約カラム | 一意性保証+検索高速化 | 主キーもUNIQUEインデックスを自動生成 |
チェックポイント: インデックスは「読み取りを速くし、書き込みを遅くする」トレードオフです。更新頻度が高いカラムへの不要なインデックスは書き込みコストを上げます。
EXPLAINで実際にインデックスが使われているか確認してから追加を判断しましょう。
実際のコードのサンプル
CREATE INDEX idx_posts_user_id_created_at
ON posts (user_id, created_at);
EXPLAIN SELECT *
FROM posts
WHERE user_id = 1
ORDER BY created_at DESC
LIMIT 20;
まとめ & 次のステップ
- インデックスはBツリー構造でフルテーブルスキャンを回避し、検索を高速化する
- WHERE・JOIN・ORDER BY で頻繁に使うカラムがインデックスの候補
- カーディナリティが低い列(フラグや性別など)にインデックスを貼っても効果は限定的
- インデックスは書き込みコストを増やすため、実測と EXPLAIN で確認してから追加する
次回は 「複合インデックスの順序」 を学びます。複数カラムをまとめたインデックスの列順がなぜ重要なのか、クエリパターンとの対応関係を具体的に確認します。