やあ。今日もデータベースと格闘してる?
PostgreSQLを触っていると、必ずと言っていいほど直面するのが「インデックスの設計」だよね。特に、複数のカラムを組み合わせた「複合インデックス(Composite Index)」は、使いこなせば最強の武器になるけれど、適当に作るとただの無駄な肥やしになってしまう。
今回は、この複合インデックスの「順序」と「最左接頭辞ルール」について、現場の知見を交えて話していくよ。これを知っているだけで、クエリの実行計画が劇的に変わるはずだ。
—
そもそも「複合インデックス」って何がすごいの?
単一カラムのインデックスを複数作るのと、複合インデックスを作るのは、似ているようで全く別物だ。
例えば、ユーザーテーブルで「苗字(last_name)」と「名前(first_name)」で検索することが多いとしよう。
CREATE INDEX idx_users_name ON users (last_name, first_name);
こうすると、PostgreSQLはB-treeという構造の中で、まず「苗字」で並べ、同じ苗字の中では「名前」で並ぶようにデータを格納する。単一インデックスを2つ作るよりも、はるかに効率的に検索範囲を絞り込めるんだ。
—
鬼門の「最左接頭辞ルール」を攻略する
ここからが本題だ。複合インデックスを語る上で避けて通れないのが「最左接頭辞ルール(Leftmost Prefix Rule)」。
簡単に言うと、「インデックスの左端から順番に使わないと、そのインデックスは効かないよ」という鉄の掟だ。
先ほどの `(last_name, first_name)` のインデックスを例に見てみよう。
- 効くクエリ:
- `WHERE last_name = ‘Sato’` (左端だけならOK)
- `WHERE last_name = ‘Sato’ AND first_name = ‘Taro’` (順番通りなら完璧)
- 効かない(または効きにくい)クエリ:
- `WHERE first_name = ‘Taro’` (左端のlast_nameがないので無視される)
「なんで?両方の名前を使いたいからインデックスを作ったのに!」と思うかもしれないけれど、B-treeの構造上、苗字がわからないと、どこから検索を開始していいか検討がつかないんだ。電話帳の「名前」だけから探そうとするようなものだね。
—
実務で意識すべき「順序」の黄金ルール
じゃあ、どのカラムを左側に持ってくるべきか? 現場で設計する時は、以下の2点を意識するといい。
1. 等価条件(=)を左側に寄せる
「ある値と一致するか」という検索条件(`=`)は、インデックスの左側に置くべきだ。範囲条件(`>` や `<`)を左側に置いてしまうと、その後のカラムがインデックスとして機能しにくくなるからね。
2. 選択性の高いものを左側に(優先度は低め)
「選択性が高い(値の種類が多い)」カラムを左に置くと、より絞り込みが早くなる。ただ、最近のPostgreSQLのオプティマイザは優秀なので、そこまで神経質にならなくてもいい。それよりも、「よく一緒に検索されるか」「等価条件か」を優先しよう。
—
具体的なチューニングの例
例えば、ECサイトの注文履歴テーブルがあるとする。
— ユーザーIDで絞って、注文日で範囲検索するケース
CREATE INDEX idx_orders_user_date ON orders (user_id, created_at);
このインデックスなら:
- `WHERE user_id = 123 AND created_at > ‘2023-01-01’` → 爆速。
- `WHERE user_id = 123` → 速い。
- `WHERE created_at > ‘2023-01-01’` → 残念ながらインデックススキャンされない(フルスキャンになる可能性大)。
もし、どうしても日付だけで検索したいケースが多いなら、それは別のインデックスを作るか、クエリ側を見直すサインだ。
—
最後に:エンジニアへのアドバイス
インデックスは「作れば作るほどいい」わけじゃない。インデックスが増えれば、データの更新(INSERT/UPDATE/DELETE)のたびにインデックスも更新しなきゃいけないから、書き込み性能が落ちるんだ。
1. EXPLAIN ANALYZE を必ず叩くこと。 インデックスが本当に使われているか、自分の目で確認する癖をつけて。
2. 迷ったらまずはシンプルな構成から。 必要以上に複雑な複合インデックスを作らない。
3. クエリの頻度を見る。 全く使われないインデックスは、勇気を持って削除する。
データベースの設計は、パズルのようで面白いよね。もしインデックスの設計で悩んだら、いつでも相談してくれ。一緒に最適な実行計画を探していこう。
それじゃ、また現場で!
コメント