MySQL の COVERING INDEX でディスクI/Oを削減する
通常のインデックス検索では、インデックスで行を特定した後、テーブル本体からデータを取得します。しかし、クエリで必要なカラムがすべてインデックスに含まれていれば、テーブル本体へのアクセスを省略できます。これを「カバリングインデックス」と呼びます。
カバリングインデックスの仕組み
通常のインデックス検索とカバリングインデックスの違いを見てみましょう。
インデックスで行を特定 → テーブル本体から全カラム取得(ランダムI/O発生)
インデックスだけで必要なカラムをすべて取得(テーブルアクセス不要)
ディスク I/O が減るため、特に大量データの検索で効果を発揮します。
カバリングインデックスの確認方法
EXPLAIN の Extra 列に Using index と表示されれば、カバリングインデックスが使われています。
-- インデックス: (user_id, status)
EXPLAIN SELECT user_id, status FROM orders WHERE user_id = 100;この場合、user_id と status はどちらもインデックスに含まれているため、テーブル本体を参照せずに結果を返せます。
| Extra: Using index | カバリングインデックス使用 |
| Extra: NULL(Using index なし) | テーブル本体へのアクセスあり |
カバリングインデックスの作り方
クエリで取得するカラムをすべてインデックスに含めます。
-- このクエリをカバリングインデックスで高速化したい
SELECT user_id, email, created_at FROM users WHERE status = 'active';
-- カバリングインデックスを作成
ALTER TABLE users ADD INDEX idx_covering (status, user_id, email, created_at);WHERE 句のカラム(status)を先頭に、SELECT するカラムをその後に配置します。
効果が大きいケース
カバリングインデックスは、以下のような場合に特に効果的です。
テーブル本体へのランダムアクセスが減るため、I/O 削減効果が大きくなります。
SSD より HDD 環境で効果が顕著です。ランダム I/O のコストが高いためです。
COUNT や SUM で大量行を処理する場合、テーブルアクセスなしで計算できます。
具体例: COUNT の高速化
ユーザーごとの注文数をカウントするケースを考えます。
SELECT user_id, COUNT(*) as order_count
FROM orders
GROUP BY user_id;(user_id) のインデックスがあれば、テーブル本体を見ずにカウントできます。
ALTER TABLE orders ADD INDEX idx_user_id (user_id);EXPLAIN で Using index が表示されていれば成功です。
注意点とトレードオフ
カバリングインデックスは万能ではありません。
| メリット | デメリット |
|---|---|
| ディスク I/O 削減 | インデックスサイズ増大 |
| クエリ高速化 | 更新・挿入が遅くなる |
| メモリ効率向上 | メンテナンス対象増加 |
インデックスにカラムを追加するほど、インデックス自体のサイズが大きくなります。書き込み性能への影響も考慮が必要です。
SELECT * を避ける理由
カバリングインデックスを活用するには、SELECT * を避けることが重要です。
-- カバリングインデックス使えない
SELECT * FROM orders WHERE user_id = 100;
-- カバリングインデックス使える可能性
SELECT user_id, status, created_at FROM orders WHERE user_id = 100;必要なカラムだけを取得する習慣をつけることで、カバリングインデックスの恩恵を受けやすくなります。
InnoDB の特性
InnoDB では、セカンダリインデックスに主キーの値が自動的に含まれます。これを利用すると、主キーを明示的にインデックスに追加しなくてもカバリングインデックスとして機能することがあります。
-- 主キー: id
-- セカンダリインデックス: (status)
-- 実際のインデックス構造: (status, id)
SELECT id, status FROM users WHERE status = 'active';
-- id は自動で含まれているため Using index になるまとめ
クエリで使うカラムを特定
WHERE 句のカラムを先頭にしたインデックス作成
SELECT するカラムもインデックスに追加
EXPLAIN で Using index を確認
カバリングインデックスは、読み取り中心のワークロードで特に有効です。ただし、インデックスの肥大化と更新性能への影響を考慮して、本当に必要な場所にだけ適用しましょう。