眠れない夜にサヨナラを。PostgreSQLの「REINDEX CONCURRENTLY」を使いこなそう
こんにちは!データベースエンジニアの現場からお届けします。
さて、皆さんはPostgreSQLのインデックスメンテナンス、どうやってますか?「とりあえず`REINDEX TABLE`を叩いて、あとは祈るだけ」なんていうヒヤヒヤする運用は、もう卒業しましょう。
特に本番環境で「テーブルロック」という悪魔と戦った経験がある人なら、一度は絶望したことがあるはずです。「あ、今ロック取っちゃった……サービスが止まった……」というあの冷や汗が出る瞬間。
今日は、そんな悪夢を回避するための最強の武器、`REINDEX CONCURRENTLY`について、現場の知見を交えてお話しします。
—
なぜ普通のREINDEXは「危険」なのか
そもそも、ただの`REINDEX TABLE`がなぜいけないのか。答えはシンプルで、「排他的ロック(ACCESS EXCLUSIVE LOCK)」を取得してしまうからです。
このロックがかかると、そのテーブルに対するSELECTすらブロックされます。数百万件ある巨大なテーブルでこれを行えば、数分間、あるいは数時間サービスが応答不能になります。深夜のメンテナンス作業でこれやっちゃうと、朝まで顔面蒼白ですよね。
そこで登場するのが `CONCURRENTLY` オプションです。
—
REINDEX CONCURRENTLY の仕組み:魔法の裏側
`REINDEX CONCURRENTLY` は、その名の通り「並行して」インデックスを再構築します。仕組みを一言で言うと、「新しいインデックスをバックグラウンドで作り、最後に古いインデックスと入れ替える」という手法です。
1. 新しいインデックスを構築: 書き込みロックを取らず、テーブルの全データをスキャンして新しいインデックスを作成します。
2. 待機: 全てのトランザクションが新しいインデックスを使えるようになるまで待機します。
3. 入れ替え: 古いインデックスを削除し、新しいものに切り替えます。
この間、アプリケーション側は完全に無停止で読み書きを続けられます。まさに「走っている馬の鞍を替える」ような離れ業ですね。
—
実践:どうやって使うのか?
使い方は至ってシンプルです。SQLでこう書くだけ。
— 特定のインデックスをオンラインで再構築
REINDEX INDEX CONCURRENTLY idx_users_email;
— テーブル単位でまとめて行う場合
REINDEX TABLE CONCURRENTLY users;
注意すべき「3つの鉄則」
現場で使うにあたって、これだけは守ってください。
- 1. トランザクションブロック内では使えない
`REINDEX CONCURRENTLY` は、それ自体が内部でトランザクションを制御しています。そのため、`BEGIN; … COMMIT;` の中で実行しようとすると「ERROR: REINDEX CONCURRENTLY cannot run inside a transaction block」と怒られます。単体で実行しましょう。
- 2. 時間がかかることを覚悟する
並行処理をする分、通常のREINDEXよりも負荷がかかり、完了までの時間も長くなります。DBのCPUやI/Oをそれなりに食うので、ピークタイムを避けるのは基本です。
- 3. 失敗した時の「ゴミ」に注意
万が一、途中でエラーが発生して止まった場合、「INVALID(無効)」なインデックスが残ることがあります。`pg_stat_user_indexes` を確認して、INVALIDなインデックスがあったら手動で `DROP INDEX` してください。放置するとパフォーマンス低下の原因になります。
—
先輩からのアドバイス:いつ使うべきか?
「じゃあ、毎日REINDEXすればいいの?」と言われると、そうではありません。
PostgreSQLのインデックスは、MVCCの仕組み上、削除や更新が繰り返されると「肥大化(Bloat)」します。`REINDEX CONCURRENTLY` は、この肥大化したインデックスをスリムにするための特効薬です。
- 適応タイミング: `pgstattuple` などの拡張を使ってインデックスの空き容量率を確認し、明らかに肥大化している場合。
- やってはいけないこと: 闇雲な定期実行。単に負荷をかけるだけです。インデックスのメンテナンスは、必要だという確証を持って行うのがプロの仕事です。
—
まとめ
`REINDEX CONCURRENTLY` は、PostgreSQLを運用する上で、エンジニアのメンタルを救ってくれる素晴らしい機能です。
「ロックを取るから怖い」という理由でメンテナンスを先延ばしにしていたインデックスがあれば、ぜひ一度検証環境で試してみてください。一度この安心感を覚えると、もう元には戻れませんよ。
皆さんのデータベースが、今日も健やかでありますように!それでは、また。
コメント