頻出高 ⏱ 6分★★★★★

インデックスの基本

左端ルール・カバリング・無効化パターンを完全習得

テーブルの特定列に対して作成する検索高速化用のデータ構造。本の索引と同様、全ページをめくらずに目的の行に素早くアクセスできる。

100 万行テーブルで顧客 ID=12345 を検索
方法アクセス行数典型速度
Full Table Scan(インデックスなし)100 万行すべて数秒〜数十秒
B 木インデックス参照約 20〜30 行(深さ log N)数ミリ秒
B 木の深さは log₂(100 万) ≈ 20。行数が増えても検索ステップ数の増加は緩やか。
-- 単一列インデックス
CREATE INDEX idx_顧客名 ON 顧客 (顧客名);

-- 複合インデックス(列の順序が重要)
CREATE INDEX idx_部門給与 ON 社員 (部門ID, 給与);

-- ユニークインデックス(UNIQUE 制約と同等)
CREATE UNIQUE INDEX idx_メール ON 顧客 (メールアドレス);

-- 削除
DROP INDEX idx_顧客名;
CREATE INDEX idx ON 社員 (部門ID, 給与) の場合
WHERE 条件インデックス理由
WHERE 部門ID = 'D01'✅ 使える先頭列で検索
WHERE 部門ID='D01' AND 給与 > 500✅ 最効率両列で検索
WHERE 給与 > 500❌ 使えない先頭列をスキップ不可
複合インデックスは先頭列から順に使う(左端ルール)。先頭列を含まない条件では効果がない。

SELECT で取得する列すべてがインデックスに含まれている場合、テーブル本体を読まずにインデックスだけで完結する。I/O が大幅に削減される。

-- 顧客名・電話番号の複合インデックス
CREATE INDEX idx_cover ON 顧客 (顧客名, 電話番号);

-- テーブル本体を読まずにインデックスだけで完結
SELECT 電話番号 FROM 顧客 WHERE 顧客名 = '山田';
よくある無効化の原因と対策
書き方問題対策
WHERE UPPER(氏名) = 'TANAKA'列に関数を適用関数ベースインデックスを作る
WHERE 氏名 LIKE '%田%'前方一致でない LIKELIKE '田%' なら使える
WHERE 年齢 + 1 = 30列の計算WHERE 年齢 = 29 に書き換え
WHERE 区分 != '削除'大多数の行を返す否定選択率を下げる条件を優先
数値列を文字列で比較暗黙の型変換で無効化型を揃える
追加コストとのトレードオフ
観点インデックスありインデックスなし
SELECT(絞り込み)✅ 高速❌ 遅い(大テーブル)
INSERT / UPDATE / DELETE❌ 索引更新コスト発生✅ 速い
ストレージ❌ 索引ファイル分追加✅ 最小
メンテナンス❌ 定期 REBUILD が必要✅ 不要
更新が非常に多いテーブルに大量のインデックスを作ると更新性能が劣化する。必要なものだけ作る。

📝 理解度チェック

複合インデックス (部門ID, 給与) に対して WHERE 給与 > 500 だけの条件でインデックスが使われない理由はどれか?
カバリングインデックスの効果として正しいのはどれか?
インデックスが無効化される WHERE 条件はどれか?

読了ボタンを押すとトップページの進捗に反映されます