まず、DBのインデックスとは
一言でいうと、「データを高速に検索するための補助データ構造」 のこと。
インデックスとは「書き込み時のコストと引き換えに、読み取りを高速化する補助構造」。テーブル本体とは別に存在し、主にBツリー(他にもある)で実装される。
本の索引と同じ概念
【索引なし】
本を最初から最後まで全ページめくって探す
→ フルテーブルスキャン(O(n))
【索引あり】
巻末の索引で「田中 → 243ページ」とわかる
→ インデックスで該当行に直接アクセス(O(log n))
DBにおける実体
テーブルとは 別に作られる、検索用のデータ構造です。
-- テーブル本体
CREATE TABLE users (
id INT,
name VARCHAR(50),
age INT
);
-- インデックスを別途作成
CREATE INDEX idx_age ON users(age);
idx_age というBツリー構造が裏側に作られ、age の値と 実際の行の場所(ポインタ) が格納されます。
作成できるインデックスの種類
① 単一列(最も基本)
CREATE INDEX idx_age ON users(age);
② 複合インデックス(複数列をまとめて)
CREATE INDEX idx_name_age ON users(last_name, first_name);
③ 式・関数インデックス(計算結果に対して)
-- 大文字小文字を無視した検索に対応
CREATE INDEX idx_lower_email ON users(LOWER(email));
④ 部分インデックス(条件付き/PostgreSQL等)
-- is_deleted = false の行だけにインデックスを張る
CREATE INDEX idx_active_users ON users(name) WHERE is_deleted = false;
⑤ 全文検索インデックス(テキスト検索用)
CREATE FULLTEXT INDEX idx_content ON articles(body);
現場での使用頻度
| 種類 | 頻度 | 理由 |
|---|---|---|
| 単一列 | ★★★★★ | ほぼ必ず使う。基本中の基本 |
| 複合 | ★★★★☆ | JOINやWHERE複数条件で頻出 |
| 式・関数 | ★★☆☆☆ | 知ってる人が使う。やや玄人向け |
| 部分 | ★★☆☆☆ | PostgreSQL現場では使われる。MySQL現場は少ない |
| 全文検索 | ★★☆☆☆ | 専用サービス(Elasticsearch等)に委譲されがち |
現実的な優先度
まず確実に押さえる
→ 単一列・複合インデックス
次に知っておくと武器になる
→ 式・関数インデックス(インデックスが効かない問題の回避)
→ 部分インデックス(PostgreSQL案件なら)
必要になったら調べる
→ 全文検索インデックス
検索の流れ
SELECT * FROM users WHERE age = 30;
① idx_age のBツリーを二分探索 → age=30 のポインタを取得
② ポインタを使ってテーブルの実データを取得
インデックスがなければ全行スキャンになります。
主なインデックスの種類
| 種類 | 特徴 |
|---|---|
| Bツリーインデックス | 最も一般的。 等値・範囲・ソートに強い |
| ハッシュインデックス | 等値検索のみ超高速。範囲検索は不可 |
| 複合インデックス | 複数列をまとめてインデックス化 |
| カバリングインデックス | インデックスだけでクエリが完結する状態 |
まとめ
今回、インデックスの勉強をしてみて、
本で言うところの索引みたいなものという理解です、
今までインデックスは、一列だけしか貼れないと思ってましたが、複数行に貼れることを発見しました。
あとはBツリー以外にもインデックスの種類があること。
このあたり深そうなので、これから暇を見つけては、インプットしたことを学習を兼ねてここにアウトプットしていきたい。