データベースインデックス

データベースインデックスとは

インデックスは、データベースの検索を高速化するための索引データです。本の巻末にある索引と同じで、「この値はどの行にあるか」をあらかじめ整理しておくことで、テーブル全体を読まずに目的の行へたどり着けます。

インデックスが無い場合、[[リレーショナルデータベース]] は条件に合う行を探すためにテーブルを先頭から全部読みます。これをフルスキャン(全表走査)と呼び、行数が増えるほど遅くなります。

仕組み — B木(B-tree)

多くのデータベースのインデックスは B木(B-tree)というデータ構造で作られています。値を大小順に並べた木構造をたどることで、100万行あっても数回の比較で目的の行に届きます。

インデックスなしインデックスあり
探し方全行を順に読む(フルスキャン)木構造をたどって直行
100万行での比較回数最大100万回20回程度
得意な条件=、範囲(BETWEEN)、前方一致

[[SQL]] の WHERE 句や [[テーブル結合(JOIN)]] の結合条件、ORDER BY で使う列にインデックスを貼るのが基本です。

貼りすぎは逆効果

インデックスは万能ではなく、書き込みのたびに索引の更新コストがかかります。

  • INSERT / UPDATE / DELETE のたびにインデックスも書き換えられるため、貼りすぎると更新が遅くなる
  • インデックス自体がディスク容量を消費する
  • 「男 / 女」のように値の種類が少ない列は、絞り込み効果が薄く効きにくい

「検索でよく使う列に、必要な分だけ」が原則です。効いているかどうかは EXPLAIN(実行計画の表示)で確認できます。

初学者向けポイント

  • [[主キーと外部キー]]のうち主キーには自動的にインデックスが作られる — 自分で貼るのは外部キーの列や検索条件・結合条件で使う列
  • 複数列をまとめた複合インデックスは列の順番が重要(先頭の列から使われる)
  • 「遅いSQLがある → まず EXPLAIN で実行計画を見る → フルスキャンならインデックスを検討」が実務の定番手順
  • LIKE '%キーワード%' のような中間一致は B木インデックスが効かない — その用途は [[全文検索]] の出番

関連技術とのつながり

  • [[SQL]] — WHERE / JOIN / ORDER BY で使う列がインデックス設計の起点
  • [[リレーショナルデータベース]] — インデックスは RDB の性能チューニングの中心
  • [[ロックとデッドロック]] — インデックスの有無はロック範囲にも影響する
  • [[全文検索]] — B木が苦手な「文章の中身の検索」を担う仕組み
  • [[実行計画とクエリチューニング]] — 貼ったインデックスが実際に使われたかを確かめる手段
Q: インデックスが無いテーブルで条件検索すると何が起きる?
- [x] テーブルを先頭から全部読むフルスキャンになる
- [ ] 検索が自動的にエラーになる
- [ ] 結果が必ず空になる
解説: インデックスが無いと条件に合う行を探すため全行を読むフルスキャンになり、行数が増えるほど遅くなります。

Q: 多くのデータベースのインデックスに使われているデータ構造はどれ?
- [ ] 連結リスト
- [x] B木(B-tree)
- [ ] スタック
解説: B木は値を大小順に整理した木構造で、大量の行があっても少ない比較回数で目的の行に届きます。

Q: インデックスを貼りすぎたときの弊害として本文で挙げたのはどれ?
- [ ] 検索結果の内容が変わってしまう
- [x] INSERT や UPDATE のたびに更新コストがかかり書き込みが遅くなる
- [ ] テーブルが自動的に削除される
解説: インデックスは書き込みのたびに更新されるため、貼りすぎると更新性能とディスク容量を圧迫します。