データベース設計

複合インデックス ふくごういんでっくす

複合インデックス複数カラム検索最適化クエリインデックス設計カバリングインデックス
複合インデックスについて教えて

簡単に言うとこんな感じ!

複合インデックスは「複数の条件をまとめて引ける分類ラベル」だよ!図書館で「著者名」だけで探すより「著者名+出版年」でラベルを作っておくほうが、特定の本にもっと速く辿り着けるよね。複合インデックスはそれと同じで、複数カラムを組み合わせた条件での検索をまとめて速くする仕組みなんだ!


複合インデックスとは

複合インデックス(Composite Index・連結インデックス) とは、2つ以上のカラムを組み合わせて作成するインデックスです。たとえば「ユーザーIDと注文日時」の組み合わせや「会社IDと部署IDと氏名」のような複数カラムによる検索を高速化します。

単一カラムのインデックスを複数作るよりも、複合インデックス1つのほうが「複数条件のセット検索」には効果的なことが多いです。たとえば WHERE user_id = 5 AND created_at > '2026-01-01' という検索に対しては、user_idcreated_at の複合インデックスが最も効率的に機能します。

複合インデックスで最も重要なのが 「カラムの順番」 です。インデックス定義の左から順に使われる性質(前置一致の原則)があるため、検索パターンに合わせた順序設計が必要です。「左端のカラムを使わない検索にはインデックスが効かない」という制約をしっかり理解しておきましょう。


複合インデックスの前置一致の原則

CREATE INDEX idx ON orders (user_id, status, created_at) を作成した場合:

検索条件インデックスが使われるか
WHERE user_id = 5✅ 使われる(先頭カラム)
WHERE user_id = 5 AND status = 'shipped'✅ 使われる(先頭から2列)
WHERE user_id = 5 AND status = 'shipped' AND created_at > '2026-01-01'✅ 最大限に使われる
WHERE status = 'shipped'❌ 使われない(先頭の user_id がない)
WHERE user_id = 5 AND created_at > '2026-01-01'⚠️ user_id 部分のみ使われる
インデックス (user_id, status, created_at) のイメージ:

[user_id=1, status=pending,    created_at=2026-01-05] → 行21
[user_id=1, status=pending,    created_at=2026-03-11] → 行87
[user_id=1, status=shipped,    created_at=2026-02-14] → 行43
[user_id=2, status=completed,  created_at=2026-01-01] → 行66
[user_id=5, status=processing, created_at=2026-04-01] → 行12
  ↑ まず user_id で絞り、次に status で絞り、最後に created_at で絞る

歴史と背景

  • 1970年代 — ISAM(Indexed Sequential Access Method)の多キーインデックスが複合インデックスの原型
  • 1980年代 — Oracle・DB2 などが CREATE INDEX ... ON (col1, col2) の複合インデックスをサポート。複雑なクエリの最適化に使われ始める
  • 1990年代 — クエリオプティマイザ(実行計画の自動最適化)が高度化し、複合インデックスを効率的に使える場面が増える
  • 2000年代 — カバリングインデックス(後述)の概念が普及。SELECT するカラムもインデックスに含めることでテーブルアクセス自体を省略する最適化が注目される
  • 現在 — クラウドDB・大規模データ処理環境では、インデックス設計がシステムパフォーマンスの最重要課題の1つに。インデックスアドバイザー機能を持つDBMSも増加

カバリングインデックスと設計パターン

通常インデックス vs カバリングインデックス 通常の複合インデックス INDEX ON orders (user_id, status) SELECT created_at FROM orders WHERE user_id=5 AND status='shipped' → created_at はインデックスにない インデックスで行を特定 → さらにテーブル本体にアクセス テーブルアクセス2回発生 カバリングインデックス INDEX ON orders (user_id, status, created_at) SELECT created_at FROM orders WHERE user_id=5 AND status='shipped' → created_at もインデックスに含まれる! インデックスだけで全情報取得完了 → テーブル本体へのアクセス不要 テーブルアクセスを省略でき超高速
-- 複合インデックスの作成
CREATE INDEX idx_orders_user_status ON orders (user_id, status);

-- カバリングインデックス(SELECT列もインデックスに含める)
CREATE INDEX idx_orders_covering
ON orders (user_id, status, created_at);

-- インデックスが使われているか確認
EXPLAIN ANALYZE
SELECT created_at FROM orders
WHERE user_id = 5 AND status = 'shipped';
-- "Index Only Scan" と表示されればカバリングインデックスが効いている

関連する規格・RFC

規格・RFC番号内容
ISO/IEC 9075 (SQL標準)CREATE INDEX 文に複数カラムを指定できる仕様

関連用語