インデックスの基礎 — なぜ検索が速くなるのか

データベースのインデックスの仕組みを、本の索引にたとえて解説します。なぜ検索が速くなるのか、どの列に貼るべきか、効かないケースや貼りすぎの弊害まで、概念から整理します。

テーブルのデータが増えると、検索が遅くなっていきます。これを解決するのがインデックス(索引)です。インデックスはデータベースのパフォーマンスを支える重要な仕組みで、「なぜ速くなるのか」を理解すると、設計やチューニングの勘所がつかめます。この記事は概念の理解に重点を置きます。

本の索引と同じ仕組み

分厚い本から「ある単語」を探すことを考えます。最初のページから順に読んでいけば必ず見つかりますが、時間がかかります。一方、巻末の索引を引けば「その単語は 245 ページ」とすぐ分かります。

データベースのインデックスも同じです。インデックスがないと、データベースは全行を上から順に調べます(フルスキャン)。インデックスがあれば、索引をたどって目的の行に直接ジャンプできます。データ量が多いほど、この差は劇的になります。

仕組み: B-tree

多くのデータベースのインデックスは B-tree(ビーツリー)という木構造で作られています。値が大小の順に枝分かれして並んでいて、探したい値へ数回のステップでたどり着けます。

イメージとしては、辞書を引くのに似ています。「さ行 → し → しん…」と絞り込んでいくように、木をたどって候補を一気に狭めます。全ページをめくるのに比べて、比較の回数が圧倒的に少なくて済みます。

どの列に貼るべきか

インデックスは、検索や結合の条件によく使われる列に貼ると効果的です。

  • WHERE の条件になる列WHERE email = ...email など
  • JOIN の結合キーON orders.customer_id = customers.id の外部キー側
  • ORDER BY で並べ替える列:並べ替えを索引の順序で肩代わりできる

逆に、めったに検索しない列や、値の種類が極端に少ない列(例: 性別のように 2 種類しかない)には、貼っても効果が薄いことがあります。

効かないケース

インデックスがあっても使われないことがあります。代表的なのは、列に加工をした条件です。

query.sql
-- 列を加工すると、その列のインデックスが使われないことがある
WHERE LOWER(email) = 'a@example.com'
WHERE age + 1 = 30

email にインデックスがあっても、LOWER(email) は「加工後の値」なので、元の列の索引と一致せずフルスキャンになりがちです。条件はできるだけ列をそのまま使う形に書くと、インデックスが効きやすくなります。

また、テーブルの大部分がヒットするような条件では、索引をたどるより全部読んだほうが速い、とデータベースが判断してインデックスを使わないこともあります。

貼りすぎの弊害

「速くなるなら全部の列に貼ればいい」とはなりません。インデックスにはコストがあります。

  • 書き込みが遅くなる:行を追加・更新・削除するたびに、インデックスも更新する必要がある
  • ディスクを消費する:インデックスは実データとは別に保存される

つまりインデックスは「検索は速く、書き込みは遅く」というトレードオフです。読み取りが多い列に絞って貼る、というバランス感覚が大切です。

まとめ

  • インデックスは本の索引と同じで、全行を調べずに目的の行へ直接たどり着ける
  • 多くは B-tree 構造で、値を大小順にたどって候補を絞る
  • WHERE / JOIN / ORDER BY でよく使う列が候補
  • 列を加工した条件では効かないことがある
  • 貼りすぎると書き込みが遅くなり容量も食う(トレードオフ)

インデックスは「なぜ遅いのか」「どうすれば速くなるのか」を考える出発点です。仕組みを知っておくと、データベースと向き合うときの視野が広がります。

手を動かして確認しましょうブラウザ上で SQL を書いて実行・自動採点できる演習問題に挑戦できます。
問題一覧へ →