【実務・中級編】 式インデックス (Expression Indexes) – PostgreSQL

「とりあえずカラムにインデックスを貼る」

エンジニアになりたての頃、僕もよくやっていました。でも、ある時気づくんですよね。「あれ? `WHERE`句で関数を通すと、せっかく貼ったインデックスが無視されるぞ?」と。

PostgreSQLを触っていて、パフォーマンスの壁にぶつかったときに最強の武器になるのが、今回紹介する「式インデックス(Expression Indexes)」です。これ、知っているだけで設計の引き出しがグッと増えますよ。

—

そもそも、なぜ普通のインデックスじゃダメなのか

例えば、ユーザーのメールアドレスを保存しているテーブルがあるとします。検索はいつも「小文字に変換してから」行いたいとしましょう。

SELECT FROM users WHERE LOWER(email) = ‘example@gmail.com’;

このクエリを高速化しようとして、`email` カラムにB-treeインデックスを貼っても、PostgreSQLはそれを使ってくれません。なぜなら、インデックスの中身は `Example@Gmail.com` かもしれないのに、クエリ側は `lower(email)` という「計算結果」を求めているからです。データベースからすれば「計算後の値がインデックスにあるか分からないから、全件スキャンしたほうが安全だよね」という判断になるわけです。

ここで登場するのが、式インデックスです。

式インデックスの書き方:魔法のカッコ

やり方は簡単です。インデックスを作成する際に、カラム名ではなく「式」をそのまま書くだけ。

CREATE INDEX idx_users_lower_email ON users (LOWER(email));

これだけで、PostgreSQLは「`LOWER(email)` という計算結果」をあらかじめ計算して、その値をツリー構造に保持してくれます。実行計画(`EXPLAIN`)を見ると、しっかりとインデックスが使われているのが確認できるはずです。

実務で「これ使える!」と思ったシーン3選

僕が現場でよく使う、特に恩恵が大きいパターンをいくつか紹介します。

1. JSONBの特定キーを狙い撃ちする

最近のPostgreSQL案件だと、設定情報をJSONBで持つことも多いですよね。でも、JSONBの中身を毎回検索すると重い。

— JSON内の ‘status’ キーが ‘active’ なレコードを探す
CREATE INDEX idx_users_status ON users ((data->>’status’));

これをしておくだけで、複雑なドキュメント構造の中でも爆速で検索が通ります。

2. 氏名の「姓名」検索を楽にする

例えば、姓と名が分かれていないカラムで、検索条件として「空白を除去して検索したい」というケース。

CREATE INDEX idx_users_name_nospace ON users (REPLACE(full_name, ‘ ‘, ”));

ユーザーがどんな入力の仕方をしてきても、このインデックスがあればヒットさせられます。

3. NULL除けのフィルタリング

「退会していないユーザー(`deleted_at IS NULL`)だけを頻繁に検索する」といったケースでは、そもそもNULL以外のインデックスを作ってしまうという手もあります。

CREATE INDEX idx_active_users ON users (id) WHERE deleted_at IS NULL;

(これは厳密には「部分インデックス」という機能ですが、式インデックスとセットで覚えておくと無敵です)

—

注意点:使いすぎは「諸刃の剣」

ここまで読んで「じゃあ全部式インデックスにすればいいじゃん!」と思ったあなた、ちょっと待って。

式インデックスは、「データの更新(INSERT/UPDATE)が発生するたびに、その計算コストが乗っかる」というデメリットがあります。複雑すぎる関数をインデックスにすると、書き込み性能がガタ落ちします。

  • 読み込み速度とのトレードオフを意識する: 頻繁に更新されるカラムなら、計算量を減らすか、そもそもカラム自体を分離(正規化)することを検討すべきです。
  • クエリと完全に一致させる: `LOWER(email)` でインデックスを作ったなら、クエリも必ず `LOWER(email)` でなければなりません。`lower(email)` と大文字小文字が混ざるだけでもインデックスは効かなくなるので注意してください。

最後に:データベースと対話しよう

データベースエンジニアの仕事って、実は「どうすればDBが一番喜ぶか」を考えることなんですよ。

「このクエリ、なんで遅いんだろう?」と悩んだら、まずは `EXPLAIN ANALYZE` を叩いてみてください。そして、「あ、関数を通しているせいでインデックスが使われていないな」と気づいたら、迷わず式インデックスを試す。

この積み重ねが、数年後のあなたを「インデックスの魔術師」にしてくれます。まずは開発環境の小さなテーブルで、ぜひ試してみてくださいね。

それでは、また次回の記事で!

コメント

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