【テクニカル・上級編】 VACUUM ANALYZE – PostgreSQL

なぜ今さら『VACUUM ANALYZE』を語るのか

PostgreSQLを触り始めて数年、あるいは数十年。誰もが一度は「なぜクエリが急に遅くなったんだ?」と頭を抱えた経験があるはずです。インデックスは貼った、WHERE句も適切だ。なのに実行計画を見ると、なぜかseq scanが選択されている。

その原因の9割は、統計情報の鮮度不足か、あるいはMVCCの代償である「ゴミ」の蓄積にあります。

`VACUUM ANALYZE`。コマンドとしてはあまりに基礎的ですが、これを「なんとなくcronで回しているメンテナンス作業」と捉えているか、「クエリプランナと対話するための重要なパイプライン」と捉えているかで、大規模システムでのエンジニアリングの質は大きく変わります。今日は、少し深いレイヤーの話をしましょう。

MVCCとガベージコレクションの「静かなる攻防」

PostgreSQLのMVCC(多版同時実行制御)において、UPDATEやDELETEは物理的な削除を行いません。古いタプルを「Dead Tuple」として残し、新しいタプルを書き込む。これは高並行性には必須のアーキテクチャですが、ストレージの肥大化とスキャン効率の低下という負債を伴います。

`VACUUM`の真の価値は、単にストレージを解放することではありません。「FSM(Free Space Map)」を更新し、次にINSERTされるタプルがどのページに収まるべきかを効率化することにあります。

もしあなたのシステムで、特定のテーブルで頻繁に更新が発生しているのに、`VACUUM`が追い付いていないなら、プランナは「テーブルの物理サイズ」と「可視タプルの密度」の計算を誤ります。結果として、Index Scanよりもコストが低いと誤認されたSeq Scanが選ばれる——これが、パフォーマンス劣化の典型的なシナリオです。

ANALYZEが「プランナの目」を曇らせる時

一方で、`ANALYZE`はクエリプランナのための「地図」を作成するプロセスです。ヒストグラムや最頻値(MCV)を更新することで、プランナは「どの値がどれくらい出現するか」を予測します。

しかし、ここで注意すべきなのが「サンプリングの精度」です。`default_statistics_target`の設定値が低いままで、極端に偏ったデータを持つカラムを放置していませんか?

  • 統計情報の罠: データの分布が偏っているカラムに対してサンプリングが不十分だと、プランナは「全レコードの1%」と予測したものが、実際には「50%」という事態を招きます。これはNested Loopが選ばれるべきところでHash Joinが暴走する原因になります。
  • 解決策: 全てを`VACUUM ANALYZE`に任せるのではなく、重要なカラムに対しては個別に`ALTER TABLE … SET STATISTICS`を使い、ヒストグラムのバケット数を調整する。この「手当て」こそが、熟練のエンジニアがやるべきチューニングです。

パフォーマンストラブルシューティングの視点

もし本番環境で「謎の低速化」に直面したら、まず以下の視点でシステムを見てみてください。

1. autovacuumのログを確認せよ: `log_autovacuum_min_duration`を設定していますか? 「どのテーブルが、どれくらいの頻度で、どれくらいの時間をかけて掃除されているか」を可視化しないのは、航海図なしで船を出すようなものです。
2. dead tupleの蓄積速度: `pg_stat_user_tables`を監視し、`n_dead_tup`が異常に積み上がっていないか。もし増え続けているなら、それは`VACUUM`の頻度不足ではなく、長期間開かれたままの「トランザクション(アイドル状態の接続)」が原因である可能性が高いです。PostgreSQLにおいて、古いトランザクションは`VACUUM`の最大の敵です。
3. IO飽和とのトレードオフ: `VACUUM ANALYZE`は強力ですが、大量のIOを消費します。ピーク時にバッチで走らせれば、たちまちレイテンシが跳ね上がります。`autovacuum_vacuum_cost_limit`と`autovacuum_vacuum_cost_delay`を適切に調整し、システムの負荷曲線に合わせた「静かなメンテナンス」を設計してください。

結論:メンテナンスは「調整」ではなく「設計」

結局のところ、`VACUUM ANALYZE`は単なる掃除用コマンドではなく、データベースとアプリケーションの対話です。

「データがどう変化するか」を予測し、プランナが常に最適な実行計画を選択できるように環境を整えてやる。この泥臭い積み重ねこそが、最高峰のデータベースエンジニアが提供できる「安定したパフォーマンス」の正体です。

教科書通りの設定で満足せず、自分の環境特有のデータ分布やアクセスパターンを読み解いてみてください。PostgreSQLは、こちらが歩み寄れば必ずそれに応えてくれる、非常に正直なデータベースですから。

—
追伸:もし特定のクエリの計画がどうしても改善しない時は、`EXPLAIN (ANALYZE, BUFFERS)`の結果を持ってきてください。そこには、まだあなたが気づいていない「統計情報の嘘」が隠れているはずです。

コメント

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