【テクニカル・上級編】 空き領域マップ(FSM) – PostgreSQL

PostgreSQLの「空き領域マップ(FSM)」:パフォーマンスの深淵を覗く

PostgreSQLを長年触っていると、誰しも一度は「なぜ、こんなにもINSERTが遅いのか?」という壁にぶつかります。もちろん、インデックスの過多やWALのボトルネックが原因であることも多いですが、現場で意外と見落とされがちなのがFSM(Free Space Map)という小さな、しかし極めて重要な存在です。

今日は、PostgreSQLのコアアーキテクチャの中でも、データベースの「目利き」とも言えるFSMについて、少しマニアックな視点で掘り下げてみましょう。

FSMとは何か:物理構造の「地図」

PostgreSQLにおいて、新しいレコード(タプル)を挿入しようとするとき、PostgreSQLは「どのページに十分な空きがあるか」を知る必要があります。もしFSMがなかったらどうなるか? 全てのページを先頭から順にスキャンして、空き領域を探さなければなりません。想像するだけで恐ろしいオーバヘッドですよね。

FSMは、各リレーション(テーブルやインデックス)ごとに作成される「フォーク(fork)」の一種で、物理的には`_fsm`という拡張子で管理されています。これは、各ページにどれだけの空き領域があるかを保持している「階層的なビットマップツリー」のような構造をしています。

階層構造の妙:なぜ「近似値」なのか

ここが面白いポイントなのですが、FSMは各ページの正確な空きバイト数を保持しているわけではありません。1バイト単位で正確な値を追跡するのは、更新負荷が高すぎるからです。

FSMは、空き領域の量を「0〜255」の段階に量子化して管理しています。

  • 0は空きなし。
  • 255はほぼ空。

この値を階層化し、上位レベルのノードには、その配下にある子ノードの中で「最大の空き領域を持つページ」の情報が格納されます。

つまり、INSERT時にはルートノードからこの木構造を辿り、「どこに十分なスペースがあるか」を効率的に推測するわけです。この「近似値による高速な探索」こそが、PostgreSQLが数百万件のテーブルに対しても高速な書き込みを実現している秘訣です。

パフォーマンストラブルの現場から:FSMが「嘘」をつくとき

ベテランエンジニアなら経験があるはずです。テーブルを大量にVACUUMしても、ディスク使用量がいっこうに減らず、かつINSERT性能も上がらない。そんな時、FSMがボトルネックになっている可能性があります。

FSMのオーバーフローと「ページ拡張」

何らかの原因でFSMの情報が古くなったり、あるいは過度な断片化(フラグメンテーション)が起きると、PostgreSQLはFSMを信じられなくなり、テーブルの末尾に新しいページを拡張(Extend)し始めます。これが続くと、物理サイズだけが肥大化し、メモリ効率も悪化する悪循環に陥ります。

トラブルシューティングのヒント

もし、更新頻度が高いテーブルで「INSERTが頭打ちになっている」と感じたら、以下の点を確認してみてください。

1. `pg_freespace`拡張の活用: `SELECT FROM pg_freespace(‘your_table’, 0)` を使えば、実際のページの状態を覗けます。FSMが「空きあり」と判断しているページと、実際に書き込めるページに乖離がないか確認するのです。
2. `max_fsm_pages`(過去の遺物): PostgreSQL 8.4以前ならこの設定が重要でしたが、現在は動的にFSMが管理されます。もし古い情報に引きずられているなら、一度`VACUUM FULL`や`pg_repack`等で物理的な再配置を行い、FSMをリセット(再構築)するのが近道です。
3. autovacuumの遅延: FSMはVACUUMプロセスが更新します。autovacuumが追いついていないと、FSMは「過去の死んだタプルがある場所」を空き領域として認識できず、無駄なページ拡張を繰り返します。

最後に:データベースは「生き物」である

FSMのような領域管理の仕組みは、地味です。クエリプランナのように華々しい最適化を行うわけでも、トランザクションのように整合性を保証するわけでもありません。

しかし、この小さな地図が正確でなければ、データベースは迷子になり、ディスクI/Oという名の「迷走」を始めます。

PostgreSQLを極めるということは、こうした裏方の挙動を深く理解し、エンジンの呼吸を感じることに他なりません。皆さんのデータベースが今日も元気に動いているなら、その裏ではFSMが懸命に「どこにスペースがあるか」を伝え続けているはずです。

もし次に、原因不明のINSERT性能低下に直面したら、ぜひ`_fsm`という名の地図を思い出してみてください。そこに、解決の糸口があるはずです。

コメント

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