【実務・中級編】 FILLFACTOR設定 – PostgreSQL

「データベースのパフォーマンスが突然落ちた……」

そんな時、原因の多くは「断片化(Bloat)」です。特にUPDATEが頻繁に走るテーブルでは、PostgreSQLのMVCC(多版同時実行制御)の特性上、どうしても避けられない問題ですよね。

今日は、そんな悩みを抱えるエンジニアの皆さんに、「FILLFACTOR(フィルファクタ)」という、現場で「ここぞ!」という時に使う裏技的な設定を紹介したいと思います。教科書には載っているけれど、意外と調整の仕方が分からない……そんな設定を、実戦的な視点で深掘りしていきます。

—

FILLFACTORって、そもそも何者?

簡単に言うと、「データページにどれだけデータを詰め込むか」を決めるパーセンテージです。

PostgreSQLは通常、データページ(デフォルトで8KB)を限界まで埋めようとします(FILLFACTOR 100%)。しかし、もし「更新」が頻繁に発生するテーブルだったらどうでしょう?

PostgreSQLのUPDATEは、実は「古いレコードを消して、新しいレコードを書き込む」という動きをします。もしページがパンパンに詰まっていたら、新しいデータは別のページに書き込まれることになりますよね。これが断片化の始まりです。

なぜFILLFACTORを下げるのか?

答えはシンプル。「余白」を作るためです。

ページ内にあえて空きスペースを作っておけば、更新された新しいレコードを「同じページ内」に書き込める可能性が高まります。これがPostgreSQLの強力な武器である「HOT(Heap Only Tuple)更新」を誘発する鍵なんです。

HOT更新ができると、インデックスの更新コストがゼロになります。これはパフォーマンスにおいて天と地ほどの差が出ます。

—

実践:FILLFACTORを調整するタイミング

では、具体的にどう設定すればいいのか。まずはテーブルの現状を確認しましょう。

— テーブルのFILLFACTORを確認
SELECT relname, reloptions
FROM pg_class
WHERE relname = ‘your_table_name’;

もし`reloptions`が空なら、デフォルトの100が適用されています。

設定のコード例

更新頻度が高いテーブルであれば、まずは「90」あたりから試してみるのが鉄則です。

— テーブルのFILLFACTORを90に変更
ALTER TABLE your_table_name SET (fillfactor = 90);

— 変更後は必ずVACUUM FULL、あるいはテーブルの再作成が必要
— (ALTER TABLEだけでは既存データには適用されません)
VACUUM FULL your_table_name;

※注意点ですが、`VACUUM FULL`はテーブルをロックするので、本番環境では注意してくださいね。最近の現場では、`pg_repack`などのツールを使ってオンラインで適用するのが一般的です。

—

どのくらい「下げれば」いいの?

ここが一番の悩みどころですよね。結論から言うと、「銀の弾丸はない」です。

  • 更新が極めて多いテーブル: 70〜80%
  • 一般的な更新頻度: 90%
  • INSERTオンリー(マスターデータ等): 100%(デフォルトでOK)

「空きスペースを増やせば増やすほど、検索効率は落ちる(ページ数が増えるのでディスクI/Oが増える)」というトレードオフがあることを忘れないでください。

私の経験則では、まずは90%に設定して、`pg_stat_user_tables` の `n_tup_upd` (更新数)と `n_tup_hot_upd` (HOT更新数)の比率を観察します。HOT更新の割合が低いなら、もう少し下げて余白を広げる、といった調整が現実的なアプローチです。

—

先輩からのアドバイス

「FILLFACTORをいじれば全て解決する」なんて魔法ではありません。一番大事なのは、「自分のアプリケーションがどの程度更新を行うのか」を正しく把握することです。

インデックスに対してもFILLFACTORは設定できます。インデックスの更新が重い場合は、インデックス側にも90%程度の設定を検討してみてください。

データベースのチューニングは、顕微鏡で細胞を見るような地道な作業ですが、ここをいじれるようになると、システム全体の挙動をコントロールしている実感が湧いてくるはずです。

もし「最近、VACUUMの頻度が高すぎて困っている」「更新処理が重い」と感じているなら、ぜひFILLFACTORをチェックしてみてください。きっと、目に見える変化があるはずですよ。

それでは、また次回の記事でお会いしましょう!

コメント

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