インデックスの「健康診断」、ちゃんとやってる?REINDEXでPostgreSQLをリフレッシュしよう
やあ。最近、データベースのパフォーマンスチューニングに追われてないかな?
「以前はサクサク動いていたクエリが、最近なんだか重い気がする……」
「実行計画を見ても、インデックスは効いているはずなのにレスポンスが悪い」
そんな悩みを抱えているなら、一度インデックスの「肥大化(Bloat)」を疑ってみるべきだ。今日は、PostgreSQLの運用で避けては通れない、インデックス再構築コマンド『REINDEX』の話をしようと思う。
—
なぜインデックスは「太る」のか?
まず前提として、PostgreSQLのMVCC(多版同時実行制御)の仕組みを思い出してほしい。
PostgreSQLでは、データ(行)を更新すると、実際には「古い行を無効にして、新しい行を別の場所に書き込む」という挙動をする。
これと同じことが、インデックスにも起きるんだ。インデックスのツリー構造の中で更新や削除が繰り返されると、使われなくなった領域が「デッドスペース」としてインデックス内に残ってしまう。これをインデックスの肥大化(Bloat)と呼ぶ。
肥大化すると何が起きるか?
1. スキャン効率の低下: 無駄な空間を読み込むために、I/Oが増える。
2. キャッシュ効率の低下: メモリ(shared_buffers)に載る有効なインデックス情報の密度が下がる。
結果として、クエリは遅くなり、ディスク容量も無駄に食うことになる。これを解消するのが`REINDEX`の役割だ。
—
基本のREINDEXコマンド
まずは基本の書き方だ。一番シンプルなのはテーブル単位での実行だね。
— 特定のテーブルの全インデックスを再構築
REINDEX TABLE users;
もし、特定のインデックスだけが極端に肥大化しているなら、それ単体で叩くこともできる。
— 特定のインデックスのみ再構築
REINDEX INDEX users_email_idx;
—
実務で一番大切な「CONCURRENTLY」の話
さて、ここからが現場の先輩からのアドバイスだ。
本番環境で上のコマンドをそのまま叩くと、対象のテーブルに排他ロック(ACCESS EXCLUSIVE)がかかってしまう。 つまり、再構築が終わるまで、そのテーブルへの読み書きが完全に止まってしまうんだ。
サービス停止が許されないシステムでこれをやると、間違いなく朝会で謝罪することになる(笑)。
そこで登場するのが `CONCURRENTLY` オプションだ。
— 本番環境の鉄則
REINDEX TABLE CONCURRENTLY users;
これを使うと、テーブルをロックせずにインデックスを裏側で作り直してくれる。時間はかかるし、CPUやI/O負荷は上がるけれど、サービスを止めずに済む。実務では「REINDEXといえばCONCURRENTLY」と体に叩き込んでおこう。
—
実行のタイミングはどう判断する?
「よし、じゃあ毎日REINDEXしよう!」と思ったそこの君、ちょっと待って。
インデックス再構築は決して軽い処理じゃない。むやみに実行すれば、逆にパフォーマンスを悪化させることもある。
目安としては、`pgstattuple` 拡張を使って「インデックスの空き率」を計測するのがおすすめだ。
— pgstattupleのインストール(一度だけ)
CREATE EXTENSION pgstattuple;
— インデックスの統計を確認
SELECT FROM pgstatindex(‘users_email_idx’);
ここで `avg_leaf_density`(リーフページの密度)が極端に低い(例えば50%以下など)場合は、再構築を検討する価値がある。
—
先輩からの教訓:運用のアドバイス
最後に、現場で戦う君たちにいくつかアドバイスを。
- 自動化は慎重に: 定期的な自動実行(cron等)は楽だけど、テーブルサイズが巨大になると再構築がいつ終わるか分からなくなる。まずは「重いな」と感じた時の手動メンテから始めて、必要に応じてスクリプト化するのが安全だ。
- VACUUMとの違い: `VACUUM`はデッドタプルを掃除して領域を再利用可能にするが、一度膨らんだインデックスの構造そのものを「作り直して引き締める」ことはできない。だからこそ、`REINDEX`が必要なんだ。
- ディスク容量に注意: `CONCURRENTLY`で実行している間は、新しいインデックスが完全に構築されるまで、古いインデックスと新しいインデックスが両方存在する。一時的にディスク容量を食うから、容量ギリギリのサーバーで実行する時は要注意だぞ。
データベースは、一度構築して終わりじゃない。こういう地味なメンテナンスを積み重ねていくことで、システムは長く、元気に動き続けてくれる。
もし「最近パフォーマンスが……」と頭を抱えていたら、まずはインデックスの状態を確認してみよう。意外と、REINDEX一発で劇的に軽くなることもあるからね。
それじゃ、また現場で会おう。健闘を祈る!
コメント