【実務・中級編】 temp_buffers – PostgreSQL

「あれ、なんか遅い…」と思ったらここを見ろ!PostgreSQLの隠れた功労者『temp_buffers』の話

現場でバリバリとクエリを書いていると、複雑な集計や中間データの保存のために、つい「一時テーブル(Temporary Table)」に頼りたくなるときってありますよね。

`CREATE TEMP TABLE tmp_results AS SELECT …`

これ、便利なんです。でも、ある日突然、大量のデータを扱うバッチ処理で「なんか妙にディスクI/Oが跳ね上がってるな?」と感じたことはありませんか?実はそれ、PostgreSQLの設定値である `temp_buffers` がボトルネックになっている可能性が高いんです。

今日は、教科書にはあまり詳しく書かれていない、でも現場では死活問題になる「temp_buffers」について、実務的な視点で深掘りしてみましょう。

—

temp_buffers ってそもそも何者?

簡単に言うと、「そのセッションが使う一時テーブル専用のメモリ領域」です。

PostgreSQLには `shared_buffers` という全セッション共通のメモリ領域がありますが、一時テーブルは「そのセッション専用」なので、わざわざ共有メモリに置く必要がない。そこで、セッションごとに専用のメモリ領域を確保して、高速に読み書きさせようというのがこの設定の狙いです。

デフォルト値は通常 `8MB` です。…正直言って、今の時代、これはかなり控えめです。

なぜこれが問題になるのか?

もし、あなたが一時テーブルで数万行、あるいは数十万行のデータをガッツリ扱っているとします。

1. データが `temp_buffers` の容量(8MB)を超えてしまう。
2. PostgreSQLは「あ、メモリに入り切らないや」と判断し、溢れた分を物理ディスク(一時ファイル)に書き出し始める。
3. ディスクI/Oが発生し、処理が一気に重くなる。

この「メモリからディスクへ溢れる」という挙動こそが、パフォーマンス低下の真犯人なんです。特に、複雑なJOINやWindow関数を多用する分析クエリでは、メモリを食いつぶすのは一瞬です。

—

実践:どうやってチューニングする?

チューニングの基本は「どれだけ溢れているかを可視化すること」です。まずは、ログを確認してみてください。

`postgresql.conf` で `log_temp_files` を `0` に設定して再起動すれば、一時ファイルが作成されるたびにログに記録されます。

— 設定例:0を指定すると、すべての一時ファイル生成がログに出る
— 実際は運用に合わせて 1024KB くらいから様子を見るのがおすすめ
ALTER SYSTEM SET log_temp_files = ‘0’;
SELECT pg_reload_conf();

ログに `temporary file: size XXXXX` と頻繁に出ているなら、それが改善のサインです。

具体的な設定変更の目安

もし、あなたのシステムが以下のような構成なら、数値を上げることを検討してください。

  • バッチ処理で巨大な一時テーブルを頻繁に作成する
  • メモリに余裕があるサーバー(32GB以上積んでるなど)

— セッション単位で設定を試すことも可能
SET temp_buffers = ’64MB’;

— バッチ処理の冒頭で設定するのもアリ
BEGIN;
SET LOCAL temp_buffers = ‘128MB’;
— ここで一時テーブルを使いまくる処理を実行
COMMIT;

ただし、注意点があります。`temp_buffers` はセッションごとに確保されるメモリです。例えば、同時に100セッションが動いている状態で `temp_buffers` を `256MB` に設定すると、理論上は `256MB 100 = 25GB` のメモリを消費する可能性があります。

「とにかく大きくすればいい」ではなく、「そのプロセスが最大でどれくらいの一時データを扱うか」を見極めて、少し余裕を持たせるのがプロの仕事です。

—

先輩からのアドバイス:そもそも一時テーブルが必要?

最後に、ちょっと意地悪な質問をさせてください。

「その一時テーブル、本当に必要ですか?」

PostgreSQLのクエリプランナは優秀です。一時テーブルを使わなくても、WITH句(CTE)や、うまくインデックスを貼ったサブクエリで同じ結果を、もっと速く出せるケースも多いです。

1. まずは `EXPLAIN ANALYZE` で実行計画を確認する。
2. 一時テーブルを使わない書き方を試す。
3. それでもダメなら、`temp_buffers` をチューニングする。

この手順を守るだけで、あなたの書くSQLは一段階上のクオリティになりますよ。

データベースエンジニアとしての腕の見せ所は、単に設定をいじることではなく、「いかにリソースを使わず、最短で結果を出すか」を考えることにあると僕は信じています。

皆さんの現場のパフォーマンスが、少しでも改善しますように。また次回の記事でお会いしましょう!

コメント

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