はじめに
ブログの記事をどう書けばいいかわからない、という疑問のサンプルのように「MySQLの検索が遅い」「ページ表示に時間がかかる」と感じていませんか? 本記事はそんな悩みに答えるため、MySQLのインデックス最適化について分かりやすく解説します。
- 目的:インデックスの役割と設計原則、実践テクニック、よくある落とし穴を体系的に学べるようにします。
- 想定読者:アプリ開発者、運用担当者、これからDB設計を学ぶ方。専門用語は必要最小限にし、具体例で補足します。
この記事を順に読めば、どのカラムにインデックスを付けるべきか、避けるべきパターン、実際の最適化手順と注意点が理解できます。各章は実務で試せる手順や確認方法を交えているので、ステージング環境で試しつつ進めてください。
以下の章立てで進めます。第2章で基礎を押さえ、第3〜5章で設計と最適化、最終的に性能測定と運用のポイントを学べます。これにより、MySQLの検索性能を効率よく改善できるはずです。
MySQLインデックスの基本と役割
インデックスとは何か
インデックスはテーブルの検索を速くするための「目次」のような構造です。書籍で目的の章をすばやく見つけるのと同じように、データの位置を素早く特定できます。主にB木(B-tree)型が使われ、値の範囲検索や等価検索を効率化します。
B木のイメージ(かんたん説明)
B木は階層構造で、上の層ほど検索対象が絞られます。電話帳を想像すると分かりやすく、まず姓の頭文字で範囲を選び、次に該当ページを開く流れと同じです。
どんな操作で役立つか
- WHEREによる検索(特に等価検索や範囲検索)
- JOINでの結合キーの探索
- ORDER BYやGROUP BYの一部(適切なカラム順の場合)
これらの操作で該当行の特定や並べ替えが速くなります。
簡単な具体例
id列に主キーインデックスがあると、id=123の検索は該当行へ直接たどれます。複合インデックスは(a,b)の順で作ると、aだけや(a,b)で効果があります。
注意点(概要)
インデックスは読み取りを速くしますが、追加・更新・削除時にメンテナンスコストが増します。頻繁に書き込むカラムは安易にインデックス化しない方が良いです。
インデックスを適用すべきカラムと避けるべきカラム
適用すべきカラム
- WHERE句で頻繁に検索するカラム
例: ユーザー検索で使うemailやuser_id。検索が速くなります。 - JOIN条件に使うカラム
例: orders.user_id と users.id の結合。結合処理の時間を減らします。 - ORDER BY / GROUP BYでよく使うカラム
例: 日付で並べ替えるcreated_at。ソートが効率化します。 - 大規模テーブルの検索対象カラム
件数が多いテーブルではインデックスの恩恵が大きいです。
避けるべきカラム
- 小規模テーブルのカラム
行数が少なければフルスキャンで十分なことが多いです。 - 頻繁に更新・削除されるカラム
例: 状態フラグやカウンタ。更新ごとにインデックスを維持する負荷が増えます。 - 低カーディナリティのカラム
例: 性別や真偽値。選択性が低く効果が薄いです。
実践的な確認ポイント
- クエリログを見て頻出カラムを優先する
- 複合インデックスは検索順序を意識する
- 長い文字列はプレフィックスインデックスで検討する
- 運用中はEXPLAINで実際の使用状況を確認する
この記事を読めば、どのカラムにインデックスを付けると効果的か、避けるべきかが具体的に判断できるはずです。
インデックス最適化の具体的な手法
適切なカラムに絞って追加
インデックスは全てのカラムに付けるべきではありません。検索・結合・ソートで頻繁に使うカラムに限定します。例:emailで検索するなら
CREATE INDEX idx_users_email ON users(email);
のように追加します。低い選択性(値がほぼ同じ)の列には効果が薄い点にご注意ください。
重複・冗長なインデックスを避ける
同じ組合せの複数インデックスや、上位列が含まれる複合インデックスと単一インデックスの重複は削除します。複合インデックスは順序が重要です。例:WHERE a=? AND b=? の場合は
INDEX(a,b)
が有効で、逆順では効率が落ちます。
カバリングインデックスの活用
クエリで必要なカラムが全てインデックス内に収まればテーブルアクセスを省けます(カバリング)。例:
INDEX(idx_a_b ON t(a,b,c))
SELECT a,b FROM t WHERE a=? AND b=?;
このときテーブルへの余分な読み込みを減らし高速化します。
LIKE句・範囲検索の最適化
前方一致(’abc%’)はインデックスが使われやすいですが、’%abc’や’%abc%’は使えません。部分一致が多い場合は全文検索エンジンや別列のプレフィックス索引(name(10))を検討してください。範囲検索(BETWEEN, >, <)はインデックスを使いますが、複合インデックスでは先頭列の絞り込みが重要です。
不要なインデックスの定期削除と監視
長期間使われないインデックスは削減しましょう。影響の大きい削除前に実行計画(EXPLAIN)やスロークエリログで確認します。ALTER TABLE … DROP INDEX で削除し、作成・削除はメンテナンス時間に行うと安全です。
小さな運用ポイント
- VARCHAR長の長い列はプレフィックス索引でサイズを抑えます。
- 統計情報は定期的に更新し、EXPLAINで効果を確認します。
- インデックス作成はバッチで行い、負荷を分散します。
インデックス設計・運用の注意点と落とし穴
概要
インデックスは検索を速くしますが、作りすぎると逆効果になります。本章では運用時に注意すべきポイントと、よくある落とし穴を具体例を交えて説明します。
インデックスが多すぎる問題
INSERT/UPDATE/DELETEはインデックスも更新します。例えばユーザー情報に多数のインデックスを付けると、大量登録時に処理が遅くなります。負荷が高い操作では不要なインデックスを外すことを検討してください。
低カーディナリティのカラム
性別や真偽値のように取り得る値が少ないカラムは、インデックス効果が限定的です。例えば性別で絞る検索が少ないなら、インデックスはオーバーヘッドになります。
小規模テーブルではフルスキャンが速い
行数が少ないテーブルでは、インデックスを使うより全件スキャンのほうが速いことがあります。定期的に実際の実行計画を確認してください。
複合インデックスと順序
複数列で検索する場合、列の順序が重要です。WHERE句でよく使う順に並べると効果が高まります。例:WHERE a AND b の場合は INDEX(a,b) が有利です。
運用上の注意
・不要なインデックスは定期的に削除すること
・インデックス作成・削除は稼働が低い時間に行うこと
・変更前にステージング環境で検証し、EXPLAINなどで効果を確認すること
よくある落とし穴
・冗長なインデックス(同等の複合索引があるのに単体索引を残す)
・インデックス名や設計のドキュメント化不足で管理が難しくなること
運用では「必要なときに作る、不要なら外す」を心がけるとよいです。
パフォーマンス測定とインデックスの使用状況確認
概要
クエリが期待どおりインデックスを使っているかを確認します。実行計画の確認、インデックス一覧の点検、ログや統計の継続監視が中心です。
EXPLAINで実行計画を読む
コマンド例: EXPLAIN SELECT …;
注目する項目: possible_keys(候補となるインデックス)、key(実際に使われたインデックス)、rows(予想スキャン行数)、Extra(Using index や Using where)。
– keyがNULLならインデックス未使用
– rowsが大きければフルスキャンの可能性
– Using indexはカバリングインデックスの指標
具体例を試して、どの条件でインデックスが選ばれるか確認してください。
SHOW INDEXでインデックス一覧を確認
コマンド例: SHOW INDEX FROM テーブル名;
見るべき点: カーディナリティ(選択性)、非同期重複(同じ先頭カラムの複数インデックス)、ユニーク性。冗長なインデックスは削除候補です。
スロークエリログとPerformance Schemaの活用
スロークエリログで実行時間の長いクエリを集め、EXPLAINで原因を特定します。Performance Schemaは頻出クエリや待機イベントを可視化します。定期的にダイジェストや統計をチェックして優先度を決めてください。
継続的監視と対応の流れ
- ログで問題クエリを検出
- EXPLAINで実行計画を確認
- 不要・冗長なインデックスをSHOW INDEXで特定
- テスト環境でインデックス追加/削除を検証
- 本番導入後もモニタリングを継続
注意点
インデックスの追加・削除はテーブルロックや書き込み影響が出ます。バックアップやメンテ時間の確保、変更前後のパフォーマンス比較を忘れずに行ってください。
まとめ:最適化のためのベストプラクティス
以下は、日常の運用で実践しやすいベストプラクティスです。
- 最小限のインデックス設計を心がける
-
必要な検索・結合・ソートに対応するインデックスだけを作成します。不要なインデックスは書き込みコストだけ増やします。
-
利用状況を定期的に分析する
-
EXPLAINや実行統計(performance_schema、slow query logなど)で実際の利用を確認します。使われないインデックスは削除候補です。
-
カバリングインデックスと複合インデックスを活用する
-
SELECTで必要なカラムがすべてインデックスに含まれるとディスクアクセスが減ります。複合インデックスは順序が重要なので、よく使うWHERE句やORDER BYの順に合わせます。
-
作成前にコストを評価する
-
インデックスは読み取りを速くしますが、INSERT/UPDATE/DELETEのコストを上げます。更新頻度の高いテーブルには慎重に追加してください。
-
変更は検証してロールアウトする
-
本番で直接作業せず、ステージングでEXPLAINや実負荷試験を行います。変更後も定期的に見直し、アプリケーションやデータ量の変化に合わせて設計を改めます。
-
簡単なチェックリスト
- どのクエリが遅いか把握する
- EXPLAINでインデックス利用を確認する
- 必要最小限のインデックスを維持する
- 削除は段階的に行いバックアップを取る
この章を参考に、定期的な観察と検証を習慣にすることで、安定したパフォーマンスを保てます。