メンテナンスの「金字塔」、REINDEX CONCURRENTLY を使いこなす
PostgreSQLと長く付き合っていると、避けて通れないのがインデックスの肥大化(Bloat)という宿命だ。特に更新頻度の高いテーブルでは、VACUUMがいくら頑張っても、インデックスのページ内には「死んだタプル」の残骸が積み重なり、クエリのパフォーマンスを静かに、しかし確実に蝕んでいく。
かつて、この「インデックスの掃除」はDBAにとって頭痛の種だった。従来の `REINDEX TABLE` は対象テーブルに強力なロック(AccessExclusiveLock)をかける。つまり、メンテナンス中は読み書きが完全に停止する。24時間365日止まれないモダンなサービスで、これを実行するのはもはやギャンブルに等しかった。
そこで登場したのが `REINDEX CONCURRENTLY` だ。PostgreSQL 12で導入されたこの機能は、まさに我々のような現場の人間にとっての福音と言える。だが、この魔法のようなコマンドの裏側で何が起きているのか、そしてなぜ「ただ便利」なだけで終わらせてはいけないのか。今日はその深淵を少し覗いてみたい。
—
REINDEX CONCURRENTLY の「二段構え」
このコマンドがロックを回避できる理由は、そのプロセスが「二段階のインデックス構築」というトリッキーな手順を踏んでいるからに他ならない。
1. フェーズ1:新しいインデックスの作成
まず、既存のインデックスとは別に、一時的なインデックスを並行して構築する。このとき、既存の書き込みオペレーションは一切阻害されない。PostgreSQLは読み取りと書き込みの両方のインデックスを参照し、整合性を保つ。
2. フェーズ2:入れ替えと破棄
新しいインデックスの構築が完了すると、古いインデックスとの置き換えが行われる。ここで初めてごく短い排他制御が発生するが、それは「ポインタの切り替え」という極めて一瞬の作業だ。
この仕組みのおかげで、我々はサービスを停止させることなく、インデックスを物理的に最適化できる。だが、ここで「じゃあ明日から全テーブルで実行しよう」と考えたなら、少し待ってほしい。
運用現場で直面する「落とし穴」
`REINDEX CONCURRENTLY` は銀の弾丸ではない。アーキテクチャ上の制約がいくつかあり、これを知らずに叩くとトラブルの引き金になる。
- トランザクションブロック内では使えない:
このコマンドは、それ自体がトランザクションを内部で完結させる必要がある。そのため、`BEGIN; REINDEX…; COMMIT;` といったブロック内では実行できない。スクリプトを書く際は注意が必要だ。
- 「失敗」した後の残骸:
もしネットワーク障害やデッドロック、あるいはディスク容量不足でコマンドが失敗した場合、「無効なインデックス(INVALID)」が残る。PostgreSQLはこれに気づかないことがある。`pg_stat_user_indexes` を確認し、`indisvalid` が `false` になっているインデックスがないか、cron等で監視するのがプロの流儀だ。
- I/O負荷の増大:
裏側でインデックスをゼロから作り直すわけだから、当然ディスクI/OとCPU負荷は跳ね上がる。ピークタイムにこれを実行するのは、自らサーバーにDDoSを仕掛けるようなものだ。必ずメトリクスを見ながら、負荷が低い時間帯を狙うか、`pg_prewarm` 等と組み合わせて負荷を制御する検討が必要になる。
—
パフォーマンストラブルシューティングの勘所
もし本番環境で `REINDEX CONCURRENTLY` を実行していて、急激にレスポンスが悪化したらどうするか?
まず疑うべきは「長期間ロックを待っているトランザクション」の存在だ。`REINDEX CONCURRENTLY` は、開始時に他のトランザクションが終了するのを待つ必要がある。この「待ち」が発生している間、後続のあらゆるクエリがブロックされる(Queueingの状態になる)。
— ロック待ちを確認するクエリの定番
SELECT pid, wait_event_type, wait_event, query
FROM pg_stat_activity
WHERE wait_event_type = ‘Lock’;
もしこれが原因でサービスが劣化しているなら、即座にメンテナンスを中断すべきだ。勇気ある撤退も、エンジニアの重要なスキルセットの一つである。
最後に
`REINDEX CONCURRENTLY` は、PostgreSQLの内部アーキテクチャの美しさを体現した機能だ。「可用性を犠牲にせずに、内部構造を最適化する」。この哲学こそが、PostgreSQLが四半世紀を超えて愛され続けている理由だろう。
しかし、どんなに便利なツールも、その仕組みを理解していないエンジニアの手にかかれば凶器に変わる。バックグラウンドで何が起きているのか、ディスクI/Oのレイテンシはどう変化しているのか、インデックスの再構築がクエリプランにどのような影響を与える可能性があるのか。そうした想像力を常に働かせて運用してほしい。
DBAの腕の見せ所は、コマンドを叩く瞬間ではなく、その前後の「静かなる設計と監視」にあるのだから。
コメント