MySQLのインデックスチューニング、何から手をつけるか
「サービスが順調に成長してきたと思ったら、急にページの表示が遅くなった」——長年Webシステムの開発・運用に携わっていると、こうした相談を数多く受けてきました。原因を調べていくと、その多くはデータベースのインデックス設計に行き着きます。
大規模サービスの開発・運用に携わる中で、MySQL・SQLServerのDBチューニングを繰り返し経験してきました。この記事では、「何から手をつければいいか分からない」という方向けに、インデックスチューニングの基本的な考え方と、実際の進め方をお伝えします。
なぜ、リリース当初は問題にならないのか
インデックスの問題が厄介なのは、データ量が少ないうちはまったく表面化しないことです。
数百件、数千件程度のデータであれば、インデックスが最適でなくても、フルスキャン(全件走査)でそれほど時間はかかりません。しかし、サービスが成長し、データが数万件・数十万件と積み上がってくると、同じクエリでも処理時間が一気に伸びていきます。
つまり、インデックス設計のツケは、サービスが「うまくいっているとき」ほど後から重くのしかかってくるということです。だからこそ、問題が起きてから対応するのではなく、成長を見越した設計と、定期的な見直しが重要になります。
まず確認すること:遅いクエリを特定する
闇雲にインデックスを追加する前に、まず「どのクエリが遅いのか」を特定することから始めます。
- スロークエリログを有効にし、一定時間以上かかっているクエリを洗い出す
EXPLAINを使って、そのクエリがどのような実行計画で処理されているかを確認するEXPLAINの結果で、typeがALL(フルスキャン)になっている箇所を重点的にチェックする
体感的に「重い」と感じる画面があっても、実際にはアプリケーション側の処理がボトルネックというケースもあります。まずはログと実行計画で、本当にDB側の問題なのかを切り分けることが最初の一歩です。
インデックス設計の基本的な考え方
1. WHERE句・JOIN句・ORDER BY句で使われるカラムに着目する
インデックスは、検索条件(WHERE)、結合条件(JOIN)、並び替え(ORDER BY)で使われるカラムに対して効果を発揮します。逆に、これらの句で使われないカラムにインデックスを張っても、効果はほとんどありません。
2. 複合インデックスは「順番」が重要
複数のカラムにまたがる複合インデックスを作る場合、カラムの並び順によって効果がまったく変わります。基本的には、絞り込み条件として先に使われるカラム、あるいは等価条件(=)で使われるカラムを先頭に置くのが定石です。
たとえば「特定のユーザーの、特定期間の注文を取得する」というクエリであれば、user_id(等価条件)を先頭に、order_date(範囲条件)を後に置いた複合インデックスが有効に働きます。
3. インデックスは「多ければ良い」わけではない
インデックスを増やしすぎると、検索は速くなっても、データの追加・更新・削除のたびにインデックスの再構築が発生し、書き込み性能が落ちてしまいます。読み取りと書き込みのバランスを見ながら、本当に必要なインデックスに絞り込むことが重要です。
実際にあった改善例:不正クチコミ分析ツールでの対応
大規模なクチコミデータを扱う分析ツールの開発において、運用チームから「不正なクチコミの影響が少なくなるランキングを作りたい」という相談を受け、検知システムと分析ロジックを設計・開発したことがあります。
大量のクチコミデータに対して、複数の条件で絞り込みながら集計するクエリが多く発生する設計だったため、集計処理でよく使われる条件の組み合わせを洗い出し、複合インデックスの順序を条件の絞り込み順に合わせて設計しました。データ量が増えていく前提のシステムだったからこそ、初期段階でのインデックス設計が、後々の運用の安定性に直結しました。
見落としがちな注意点
1. インデックスを張っても効かないケースがある
カラムに対して関数やSQL上の演算を行っている場合(例:WHERE YEAR(created_at) = 2026のような書き方)、インデックスが効かずフルスキャンになってしまうことがあります。インデックスを活かすには、カラムそのものを条件に使う書き方(例:日付の範囲指定)に見直す必要があります。
2. カーディナリティ(値の種類の多さ)を意識する
性別のように値の種類が少ないカラムにインデックスを張っても、絞り込み効果はあまり期待できません。会員IDやメールアドレスのように、値の種類が多く一意性が高いカラムほど、インデックスの効果が大きくなります。
3. 本番相当のデータ量で検証する
開発環境のデータが少ない状態で検証すると、インデックスの効果を正しく判断できません。可能であれば、本番に近いデータ量でEXPLAINを確認し、実行計画を見ながら調整することをおすすめします。
まとめ
MySQLのインデックスチューニングは、闇雲に手を動かすのではなく、次の順番で進めるのが基本です。
- スロークエリログと
EXPLAINで、本当に遅い箇所を特定する - WHERE・JOIN・ORDER BYで使われるカラムを中心に設計する
- 複合インデックスは、条件の使われ方に合わせて順番を決める
- インデックスは増やしすぎず、読み書きのバランスを見ながら絞り込む
サービスが成長してから慌てて対応するのではなく、データ量が増えることを前提に、早い段階から設計・見直しの習慣をつけておくことが、長期的に安定したシステム運用につながります。

