589 文字
3 分
DBインデックスは「本の索引」と同じ発想
データベースのインデックスは、本の巻末にある「索引」と同じ発想で作られています。本文を最初から読まずに、索引から該当ページに飛べるようにしておく。テーブルでも、特定のカラムについて並び替えた補助データを別に持つことで、目的の行に素早くたどり着けるようになります。
中身はだいたい B+Tree
MySQL(InnoDB)や PostgreSQL の標準的なインデックスは、B+Tree という木構造で実装されています。ルートから葉までの段数が少ないため、件数が億単位になっても、数回のディスク/メモリアクセスで該当行にたどり着けます。
全文検索向けには転置インデックス、地理情報向けには R-Tree、メモリ上の高速参照には Hash インデックスなど、用途に応じて別の構造もあります。
効くケース
WHERE句に出てくるカラムJOINで結合キーになるカラムORDER BY/GROUP BYのキーになるカラム- 一意性制約(PRIMARY KEY、UNIQUE)
効かない/逆効果なケース
- カーディナリティが低い:例えば「性別」のように2値しかない列に貼っても、絞り込みが弱い。
- 関数を噛ませる:
WHERE DATE(created_at) = ...のように関数で包むと、B+Tree が使えない。 - 左端一致しない複合インデックス:
(a, b, c)のインデックスに対して、WHERE b = ?だけで引いてもインデックスは使われない。 - 書き込みが多い列に貼りすぎる:INSERT/UPDATE/DELETE のたびに索引も更新する必要があるため、書き込み性能が落ちる。
設計の勘所
- クエリの形に合わせて貼る:先にクエリ、後からインデックス。アプリケーションが投げる SELECT の形を見て、必要なものだけ貼る。
EXPLAINで確認する:実際に使われているか、フルスキャンしていないかを必ず確かめる。- 複合インデックスの順序:等価比較で絞り込む列を左、レンジ検索の列を右に置くと効きやすい。
- 削れるかも検討する:使われていないインデックスは、書き込みを遅くするだけのコストになる。
「とりあえず貼る」は事故の元。投げたいクエリから逆算して、最小限のインデックスで最大の効果を狙うのが理想形です。