コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
インデックスの役割
インデックスの役割
このレッスンで分かること
- 全表走査と索引参照の計算量の違い
- インデックスがなぜ書き込みを遅くするのか
- インデックスを貼る判断基準
インデックスの役割 とは
全件走査と索引参照の違いを計算量から把握する。本レッスンでは、インデックスの役割 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。
インデックスがない世界
1000 万行のユーザーテーブルから WHERE email = 'alice@ex.com' を実行することを考えます。インデックスがなければ、DBMS は先頭行から順に 1 行ずつ email カラムを比較していきます。これを 全表走査 (Full Table Scan) と呼びます。
計算量は O(n) で、1000 万行なら最悪 1000 万回の比較が必要です。仮に 1 回 1 マイクロ秒としても 10 秒かかります。これでは Web アプリは破綻します。
インデックスがある世界
email カラムに インデックス を貼ると、DBMS は別途「email ソート済みの索引」を保持します。これを B-tree で持っていて、O(log n) で検索できます。
1000 万行なら log2(10000000) ≒ 23 で、23 回の比較で目的の行に辿り着けます。これは全表走査の 約 43 万倍 速いということです。
インデックスの内部イメージ
インデックスは 「キー値 → 行の物理位置」のソート済み索引 です。本の巻末索引と同じ発想です。
| row_pointer | |
|---|---|
| alice@ex.com | page=12, slot=3 |
| bob@ex.com | page=87, slot=1 |
| carol@ex.com | page=44, slot=9 |
email で目的のキーを二分探索し、見つかったら row_pointer を辿ってテーブル本体の行を読み込みます。
インデックスのコスト
インデックスはタダではありません。次の 3 つのコストがあります。
1. ディスク容量 — インデックス自体がデータです。10 列に貼れば、テーブルとほぼ同サイズになることも。
2. 書き込みの遅延 — INSERT / UPDATE / DELETE のたびに、関連する全インデックスを更新する必要があります。インデックスが 10 個あれば書き込みは概ね 10 倍遅くなります。
3. メモリ消費 — 高頻度に使うインデックスはバッファプールに乗ります。メモリを食う。
インデックスは「読み取りを速くする代わりに、書き込みを遅くする」トレードオフ。
インデックスを貼る判断基準
次の条件のいずれかに当てはまるカラムは候補です。
WHERE句で頻繁に使われるJOINの結合キーになるORDER BY/GROUP BYで使われる- 値の カーディナリティ(種類数) が高い
逆に、次のような列にインデックスを貼っても効果は薄いです。
- 性別カラム(値が 2-3 種類しかない)
- 削除フラグ
- ほぼ
NULLのカラム - 更新が極端に多いテーブル
カーディナリティが低い列は、インデックスを使うより全表走査のほうが速いこともあります。
複合インデックス
複数カラムを組み合わせた索引もあります。
SQL クエリ
CREATE INDEX idx_user_status_created ON orders (user_id, status, created_at);これは「user_id でソート、同値内で status でソート、さらに created_at でソート」の索引です。
左端の原則 が重要です。(user_id, status, created_at) の複合インデックスは次のクエリに効きます。
WHERE user_id = ?— 効くWHERE user_id = ? AND status = ?— 効くWHERE user_id = ? AND status = ? AND created_at > ?— 効くWHERE status = ?— 効かない(左端user_idがない)WHERE created_at > ?— 効かない
電話帳が「姓 → 名」でソートされていて、「名」だけで引けないのと同じです。
一意インデックス vs 通常インデックス
UNIQUE INDEX は値の重複を許さず、整合性制約も兼ねます。通常インデックスは検索高速化のみ。PRIMARY KEY は自動で UNIQUE INDEX になります。
クエリヒントとオプティマイザ
DBMS の クエリオプティマイザ が「どのインデックスを使うか」を決めます。複数貼ってあっても、最適なものを 1 つ選びます。意図と違うインデックスが選ばれることもあり、USE INDEX、FORCE INDEX でヒントを与えることもできます(多用は禁物)。
やってみよう
CREATE INDEXの前後で、EXPLAINの出力がどう変わるか比較するSHOW INDEX FROM table_nameで既存インデックスを確認する- 性別カラムにインデックスを貼ると本当に効くか試す(カーディナリティが低い場合の挙動)
よくある質問
Q. インデックスを貼ると遅くなる処理はありますか?
A. INSERT / UPDATE / DELETE は遅くなります。インデックス自体も更新が必要なため、書き込みが多いテーブルに大量のインデックスを貼ると書き込み性能が落ちます。読み取りと書き込みのバランスで判断し、不要なインデックスは削除しましょう。
Q. 複合インデックスは順番が大事ですか?
A. 順番が極めて重要です。(user_id, created_at) のインデックスは WHERE user_id = ? AND created_at > ? で効きますが、WHERE created_at > ? だけだと効きません。よく使う絞り込みカラムを先頭に置くのが定石です。
Q. インデックスが効いているか確認するには?
A. EXPLAIN(MySQL/PostgreSQL)または EXPLAIN ANALYZE で実行計画を見ます。type が ref / range / const なら使われていて、ALL は全件スキャン(インデックス未使用)です。意図と違うインデックスが使われている場合は USE INDEX で強制することもできます。
次のレッスン
次は B-tree の仕組み で、全件走査と索引参照の違いを計算量から把握する を学びます。
事前確認 — 進む前に次の 3 つができることを確認しましょう。
- インデックスの役割 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. インデックスの役割 とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン