今回は、大量のデータを素早く効率よく扱うために欠かせない、データベースの**インデックス(Index)**を学びます。
「インデックスを使うと検索が速くなる」と知っている人は多いでしょう。
一方、「それなら、なぜすべてのデータに使わないのか」まで考える機会は少ないかもしれません。
この疑問を手がかりに、仕組みとそのトレードオフを見ていきます。
分厚い本の最後にある索引を思い浮かべると、インデックスを理解しやすくなります。
数百ページある本で「REST API」という語を探すとしましょう。
最初から最後まで1ページずつめくるのは効率が悪い方法です。
索引の「R」の欄で「REST API」を探せば、52、108、210ページにあるとすぐわかります。
データベースのインデックスも同じ役割を果たします。
特定のデータを素早く探すために、元データとは別に作っておく
目次や索引
のようなものです。
インデックスがなければ、データベースは目的のデータを見つけるために、すべてのデータを順に調べるフルテーブルスキャン(Full Table Scan)を行います。

インデックス
インデックスを理解するうえで、中心となる疑問です。
付ける列は選ぶ必要があります。
本に出てくるすべての単語を索引に載せたらどうなるでしょうか。
索引のほうが本文よりも分厚くなりかねません。
インデックスにも利点と欠点があるため、慎重に使います。
インデックスを作る最大の理由は、
SELECT クエリの検索性能を大きく改善できる
ことです。
特に、
WHERE 句や
JOIN 条件に使う列に付けると、フルテーブルスキャンを避け、インデックスからデータの位置を特定できるため、応答が速くなります。
-- 'user_email' 컬럼에 인덱스가 걸려 있다면, 이 쿼리는 매우 빠르게 실행됩니다.
SELECT * FROM users WHERE user_email = 'student@example.com';
すべての箇所にインデックスを付けない理由は、主に2つあります。
書き込み性能の低下(Write Penalty)
SELECT とは異なり、INSERT、UPDATE、DELETE は遅くなります。
本の内容を追加したり修正したりすると、索引も直さなければならないのと同じです。
新しいデータを追加(INSERT)すると、元のテーブルに加えて、インデックスにも並び順に従って新しい情報を書き込む必要があります。
更新(UPDATE)や削除(DELETE)でも同様です。
頻繁に変わる列にむやみにインデックスを追加すると、システム全体の性能が低下する場合があります。
追加の保存領域が必要
インデックスは、元のテーブルとは別の領域を占めるデータ構造です。
作る数が多いほど、ディスク容量が必要になります。
このように、インデックスには検索性能と書き込み性能の間に
トレードオフ
があります。
長所と短所を踏まえると、次のような列に使うと効果的です。
WHERE 句で頻繁に使う列
JOIN で頻繁に使う列(外部キーには通常、自動的にインデックスが作られます)
- 並べ替え(
ORDER BY)によく使う列
- 値の重複が少なく、異なる値が多い列
例えば「男性/女性」の2値しかない性別の列よりも、ほとんどの値が異なるメールアドレスの列にインデックスを付けるほうが効率的です。後者は
カーディナリティ(Cardinality)が高い
といいます。
今回は、データベースインデックスの仕組みと、そのトレードオフを見てきました。
- インデックスは、データ検索(
SELECT)を速くする索引
のようなものです。
- すべての箇所に付けると書き込み(
INSERT、UPDATE、DELETE)が遅くなり、保存領域も必要になります。
読み取りと更新の頻度、値の重複の度合い
を考慮し、必要な箇所に絞って使います。
「インデックスを使ったことがありますか? どの列に付け、なぜそうしたのですか?」は、データベースへの理解を確かめる質問です。今日の内容をもとに、使う理由と慎重に選ぶ理由の両方を説明できるようにしておきましょう。