【実務・中級編】 TOAST領域の管理 – PostgreSQL

「PostgreSQLのテーブル設計、なんとなくデフォルトのまま作ってない?」

もしそうなら、ちょっとだけ時間をください。今日はPostgreSQLの「知る人ぞ知る守護神」、TOAST(The Oversized-Attribute Storage Technique)の話をしよう。

大規模なデータを扱うシステムを設計していると、必ずと言っていいほど「テキストカラムが肥大化して、パフォーマンスがガタ落ちする」という壁にぶつかるんだ。このとき、PostgreSQLが裏側で何をしているのか、どう制御すべきかを知っているかどうかで、エンジニアとしての価値が大きく変わる。

—

1. TOASTってそもそも何者?

PostgreSQLのページサイズはデフォルトで8KB固定だ。でも、世の中には10KBや1MBを超えるような巨大なテキストやJSONBが溢れている。

「じゃあ、そんな巨大データはどこに格納されるの?」

そこで登場するのがTOASTだ。PostgreSQLは、ある一定サイズ(デフォルトで2KB)を超えたデータを自動的に別領域へ追い出し、圧縮したり分割したりして格納する仕組みを持っているんだ。これにより、8KBという制約の中でも巨大データを扱えるようになっている。

要は、「メインのテーブル領域を汚さないための避難所」だと思っていい。

—

2. 4つのストレージ戦略:使い分けがプロの技

各カラムには、データがTOAST領域にどう扱われるかを決める「ストレージ戦略」が設定できる。これを理解するのが、パフォーマンスチューニングの第一歩だ。

  • PLAIN: TOASTを使わない。圧縮も分割もしない。小規模なカラムに最適。
  • EXTENDED: デフォルトの設定。 まず圧縮を試み、それでもデカければTOASTへ追い出す。一番汎用性が高い。
  • EXTERNAL: 圧縮はしないが、分割してTOASTへ追い出す。高速な読み取りが必要な巨大データ向け。
  • MAIN: 圧縮するが、TOASTへの追い出しは「どうしても入り切らない時だけ」にする。読み取り速度を優先したい時に使う。

—

3. 実務で「おっ」と思わせる設定術

例えば、ログを格納するテーブルで、検索には使わない巨大なJSONBカラムがあるとしよう。デフォルトのままだと、頻繁に圧縮・解凍が発生してCPUを無駄遣いする可能性がある。

そんなときは、こうやって制御するんだ。

— テーブル作成時にストレージ戦略を指定する例
CREATE TABLE system_logs (
id SERIAL PRIMARY KEY,
event_name TEXT,
payload JSONB — ここが巨大になる予定
);

— payloadカラムを「圧縮なし・分割優先」のEXTERNALに変更する
ALTER TABLE system_logs ALTER COLUMN payload SET STORAGE EXTERNAL;

ここが現場の知恵:
もし、読み取り頻度が極端に低く、ディスクI/Oを抑えたいなら、`EXTERNAL`にしておくとCPU負荷が下がる。逆に、頻繁にアクセスするなら`MAIN`を選択して圧縮後のデータがメイン領域に収まるように祈る、というのも一つの戦略だね。

—

4. 「TOASTの閾値」をいじる勇気

実は、TOASTが発動する「2KB」という閾値、これもテーブル単位で調整できるんだ。

— 5KBを超えたらTOASTに追い出すように変更
ALTER TABLE system_logs SET (toast_tuple_threshold = 5120);

「なんでこんなことするの?」と思うかもしれない。例えば、「メイン領域にはできるだけ多くの行を詰め込みたい(スキャン効率を上げたい)」という場合は、この閾値をあえて小さくする。逆に、「CPU負荷を下げて、少しでもメイン領域で完結させたい」なら閾値を上げる。

これはまさに、アプリケーションの特性とハードウェアの性能を見極めたエンジニアだけが許される「特権的な設定」だよ。

—

最後に:慢心は禁物

TOASTを理解すると「とりあえず何でも入るから安心」と思いがちだけど、それは間違いだ。

TOASTにデータが溢れると、物理的な読み取りが増えてパフォーマンスは確実に劣化する。 結局のところ、データモデルを適切に正規化して、巨大なテキストを別テーブルに分離する「テーブル設計の基本」に勝るものはないんだ。

TOASTはあくまで「最後の砦」。設計段階で、「このカラムは本当にここのテーブルに必要か?」を問い続けること。それができるエンジニアが、結局一番長く愛されるシステムを作れるんだよ。

現場からは以上だ。また何かあればいつでも聞いてくれ。

コメント

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