PostgreSQLのFSMを理解する:なぜ「空きスペース」を探すのがそれほど速いのか?
やあ。データベースのパフォーマンスチューニングにどっぷり浸かっていると、どうしても避けて通れないのが「PostgreSQLがどこにデータを書き込もうとしているのか」という話だ。
今日は、PostgreSQLの屋台骨を支える地味だけど超重要な仕組み、FSM(Free Space Map:空き領域マップ)について話をしよう。
「`INSERT`が遅い」とか「テーブルが肥大化して困る」という悩みに直面したとき、このFSMの挙動を知っているかどうかで、エンジニアとしての視界がガラッと変わるはずだ。
—
FSMって結局、何者なのか?
PostgreSQLはデータを「ページ(通常8KB)」という単位で管理している。新しいデータを挿入しようとするとき、PostgreSQLは「どのページに十分な空きスペースがあるか」を知らなければならない。
もしFSMがなかったらどうなると思う? データベースは、新しいタプルを挿入するたびに、全ページを端から順にスキャンして空き容量を確認しなければならない。そんなことをしていたら、システムは一瞬で悲鳴を上げるだろうね。
そこで登場するのがFSMだ。これは各テーブル(やインデックス)ごとに作成される「各ページにどれくらいの空きがあるか」を記録したツリー状のマップだ。これがあるおかげで、PostgreSQLは「あ、このページならまだ余裕があるぞ」と即座に判断できるわけだ。
FSMの構造を覗いてみる
FSMは、実は「各ページの空き容量を記録したツリー」だ。
具体的には、各ページを8bitの数値でランク付けしている。
- 0: 空きなし
- 255: ほぼ空っぽ
このマップはメモリ上にもロードされるが、基本的にはディスク上のファイル(`_fsm`という拡張子)に永続化されている。ここが面白いところで、FSMは「ざっくりとした目安」を管理しているんだ。正確なバイト単位の空き容量をリアルタイムで同期し続けるとオーバーヘッドが大きすぎるから、あえて「大体このくらい空いてるよ」という情報を保持する仕組みになっている。
実践:FSMがボトルネックになるケース
現場でよくあるのが、「大量の`UPDATE`や`DELETE`が発生した後に、`INSERT`の速度が極端に落ちる」というケースだ。
FSMは、ページ内の空き容量が変化するたびに更新される。だが、あまりに更新頻度が高いと、FSMの更新自体が競合してパフォーマンスを食うことがある。
もし君の環境で「データはスカスカなのに、なぜか新規挿入が新しいページをどんどん作成してテーブルが肥大化する」という現象が起きたら、まずは`pg_freespacemap`拡張を確認してみてほしい。
実際に覗いてみる方法
PostgreSQLには、FSMの状態を可視化するための便利な拡張機能がある。まずはこれを入れてみるのが第一歩だ。
— 拡張のインストール
CREATE EXTENSION pg_freespacemap;
— 特定のテーブルの空き容量を確認する
SELECT
blkno,
avail
FROM pg_freespace(‘your_table_name’)
LIMIT 10;
これで見れば、「どのページがどれだけスカスカなのか」が一目瞭然だ。もし`avail`が低いページばかりなのに、テーブルサイズばかり増えていくなら、それはFSMがうまく機能していないか、あるいは`VACUUM`が追いついていないサインかもしれない。
後輩エンジニアへ伝えたいこと
現場で「なぜか遅い」というトラブルに遭遇したとき、多くのエンジニアは「クエリの書き方」や「インデックスの有無」ばかりを気にする。それは正しい。でも、その下のレイヤー、つまりPostgreSQLがディスク上でどうやってスペースをやりくりしているかを知っていると、「`VACUUM`をもっと頻繁に回すべきか」「`fillfactor`を調整して、更新負荷に備えるべきか」という、一歩踏み込んだ議論ができるようになる。
特に`UPDATE`が多いテーブルでは、`fillfactor`を少し下げて(例えば80〜90%)、ページ内にあえて余白を残しておく設定を検討してみてほしい。そうすれば、FSMがページを探し回るコストも減り、結果としてパフォーマンスが安定する。
まとめ
- FSMは「空きスペースの地図」である。
- 正確なバイト数ではなく、効率的な検索のための「ランク」を保持している。
- `pg_freespacemap`を使って、時々自分の管理しているテーブルの「健康診断」をしよう。
データベースの仕組みは、知れば知るほど愛着が湧くものだ。ブラックボックスとして扱うのではなく、中身がどう動いているのかを想像しながら設計する。それが、君を「ただの利用者」から「熟練のデータベースエンジニア」へと変えてくれるはずだよ。
また何か気になることがあれば、いつでも聞きに来てくれ。一緒に深掘りしていこう。
コメント