2章:where句
2. 複合インデックス
複合インデックスの本質
以下のインデックスを定義した場合:
CREATE INDEX idx_emp
ON employees (社員ID, 子会社ID);
このインデックスは、次の順序で並んだ「辞書」を表す:
社員ID順 → その中で子会社ID順
左端一致ルール(最重要)
誤解
- 複合インデックスの任意の列をWHERE句で使える
正解
- 定義した順番の左から順にしか使えない
使える・使えない例
| WHERE句の条件 | インデックス利用可否 |
|---|---|
社員ID = ? |
使える |
社員ID = ? AND 子会社ID = ? |
使える |
子会社ID = ? |
使えない |
具体例① インデックスが使えないケース
インデックス定義
CREATE INDEX idx_emp
ON employees (社員ID, 子会社ID);
SQL
SELECT *
FROM employees
WHERE 子会社ID = 10;
理由
- 左端列(社員ID)が指定されていない
- インデックスの並び順と検索条件が合わない
結果
- TABLE FULL SCAN
具体例② 列順を変えて改善するケース
インデックス定義(列順変更)
CREATE INDEX idx_emp2
ON employees (子会社ID, 社員ID);
SQL
SELECT *
FROM employees
WHERE 子会社ID = 10;
理由
- 左端列(子会社ID)がWHERE句と一致
結果
INDEX RANGE SCAN- 必要な範囲のデータだけを読む
実行計画の違い(整理)
| スキャン方式 | 意味 |
|---|---|
INDEX UNIQUE SCAN |
1行に特定できる検索 |
INDEX RANGE SCAN |
条件に合う範囲の複数行を取得 |
INDEX FULL SCAN |
インデックス全体を走査 |
TABLE FULL SCAN |
テーブル全件を走査 |
列順を決める基本ルール
- WHERE句で 最もよく使われる列
- 等価条件(=)で使われる列
- 絞り込み効果が高い列
- 範囲条件(BETWEEN / > / <)は後ろ
よくある設計
よくある検索
SELECT *
FROM orders
WHERE customer_id = 100
AND order_date >= '2024-01-01';
適切なインデックス
CREATE INDEX idx_orders
ON orders (customer_id, order_date);
理由
-
customer_id = ?でまず絞る - その中で
order_dateの範囲検索
インデックス数とパフォーマンス
- インデックスが増えるほど
- SELECT は速くなる可能性がある
- INSERT / UPDATE / DELETE は遅くなる
- 一つのテーブルに対するインデックスは
「本当に使われるものだけ」 に絞る
まとめ
- プライマリキー検索は最速(
INDEX UNIQUE SCAN) - 複合インデックスは 左端一致がすべて
- 列順を変えるだけで実行計画は大きく変わる
- WHERE句を見ずにインデックス設計はできない
- 実行計画(EXPLAIN)で必ず確認する