【実務・中級編】 部分インデックス(Partial Index) – PostgreSQL

インデックス設計の「引き出し」を増やす:PostgreSQL 部分インデックスの賢い使い方

「インデックスはとりあえず貼っておけ」。新人時代、先輩からそんなアドバイスを受けて、とりあえずテーブルの主要なカラムにインデックスを貼りまくった経験はありませんか?

確かにインデックスは検索を爆速にしてくれますが、副作用もありますよね。書き込みのたびにB-treeを更新するオーバーヘッド、そして何より、肥大化するインデックスサイズ。特に数千万件規模のテーブルを扱うようになると、インデックスの「維持費」がシステムの足を引っ張り始めるものです。

今日は、そんなインデックス設計の悩みを一発で解決してくれる、僕が実務で愛用している「部分インデックス(Partial Index)」という武器を紹介します。これを知っているだけで、パフォーマンスチューニングの引き出しがグッと広がりますよ。

—

部分インデックスって何?

一言で言えば、「テーブル全体ではなく、条件を満たす行だけに絞ったインデックス」のことです。

通常のインデックスはテーブルの全行をインデックス化しますが、部分インデックスは `WHERE` 句を指定することで、「必要なデータだけ」をインデックスに詰め込みます。

これがなぜ強力なのか。理由はシンプルで、「インデックスが物理的に小さくなるから」です。サイズが小さければメモリ(shared_buffers)に載りやすくなるし、何より更新時のコストが劇的に下がります。

—

こんなシーンで使え!実戦的な活用例

例えば、「未処理のタスクだけを高速に取得したい」というような、フラグ管理されているテーブルを想像してみてください。

1. ステータスによる絞り込み(最も一般的な例)

システムによくある「完了フラグ」付きのタスクテーブル(`tasks`)があるとします。

— 完了していないタスクだけを対象にする
CREATE INDEX idx_tasks_pending
ON tasks (created_at)
WHERE status = ‘pending’;

これだけで、`status = ‘pending’` を条件に含むクエリは、この小さなインデックスを使って爆速で検索されます。逆に、完了済みのタスクがどれだけ増えても、このインデックスのサイズは一切増えません。無駄なコストをゼロにできるわけです。

2. NULLを除外する

「特定のカラムがNULLじゃないデータだけをよく検索する」というケースも多いですよね。

— 削除フラグが立っていないデータだけを検索対象にする
CREATE INDEX idx_active_users_email
ON users (email)
WHERE deleted_at IS NULL;

これもかなり効きます。多くのアプリケーションでは「論理削除」を採用していますが、アクティブなユーザーだけをインデックス化することで、検索パフォーマンスを安定させつつ、ストレージの圧迫を防げます。

—

使うときの注意点:ここだけは押さえて!

便利な部分インデックスですが、魔法ではありません。いくつか気をつけるべきポイントがあります。

  • クエリのWHERE句と一致させる必要がある

当然ですが、インデックスを作った条件(`WHERE status = ‘pending’`)と、クエリの `WHERE` 句が合致していないと、インデックスは使われません。例えば、`SELECT FROM tasks WHERE status = ‘done’` というクエリには、上の `idx_tasks_pending` は一切役に立たないんです。

  • 「とりあえず全件検索」には使えない

条件を指定しないクエリには当然使えません。あくまで「特定の属性を持つデータへのアクセス」を最適化するためのものだと割り切りましょう。

  • 更新頻度とのトレードオフ

条件に含まれるカラム(上の例なら `status`)を頻繁に書き換える場合、インデックスの入れ替えが発生するため注意が必要です。とはいえ、全行インデックスよりは負荷が軽いケースがほとんどです。

—

先輩からのアドバイス

実務で部分インデックスを導入する時は、まずは 「実行計画(EXPLAIN ANALYZE)」 を見てください。

「あれ、このクエリ、インデックス使われてないな?」と思った時、テーブル全体にインデックスを貼る前に、「本当に検索しているデータセットは、テーブル全体の何パーセントか?」と自問自答してみてください。

もしその割合が小さければ、迷わず部分インデックスを検討しましょう。ディスク容量の節約にもなりますし、DBからの「ありがとう」という声が聞こえてくるくらい、クエリのレスポンスが改善するはずです。

データベースは、ただデータを貯める箱じゃありません。どう効率的に出し入れするか、その設計の深みがエンジニアとしての腕の見せ所です。ぜひ、次のタスクから「部分インデックス」を設計の選択肢に入れてみてください。

さて、次はどのインデックスの話をしようかな。また現場で会いましょう!

コメント

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