【実務・中級編】 複合インデックス – PostgreSQL

やあ。今日もデータベースと格闘してる?

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. クエリの頻度を見る。 全く使われないインデックスは、勇気を持って削除する。

データベースの設計は、パズルのようで面白いよね。もしインデックスの設計で悩んだら、いつでも相談してくれ。一緒に最適な実行計画を探していこう。

それじゃ、また現場で!

コメント

タイトルとURLをコピーしました