【実務・中級編】 共有バッファプール – PostgreSQL

PostgreSQLの「共有バッファ(Shared Buffers)」を攻略して、パフォーマンスの壁を突破しよう

やあ。最近、PostgreSQLのパフォーマンスチューニングに頭を悩ませている後輩が増えてきた気がするね。

「SQLは最適化したはずなのに、なぜかレスポンスが改善しない…」
「大量の読み込みが発生すると、急にデータベースの負荷が跳ね上がる…」

そんな時に、一番最初に見るべきポイントが「共有バッファ(shared_buffers)」だ。今日は、教科書的な説明はさらっと流して、現場で役立つ「なぜそれが重要なのか」という本質的な話をしよう。

—

1. そもそも共有バッファは何をしているのか?

一言で言うと、PostgreSQLの「作業机」だと思えばいい。

ディスク(SSDやHDD)からデータを読み込むのは、どんなに速いストレージを使っても、メモリから読み込むのに比べれば「永遠」とも言えるほど遅い。だから、PostgreSQLは一度読んだデータをメモリ上にキャッシュしておくんだ。その場所が共有バッファだ。

もし必要なデータが共有バッファにあれば、ディスクを叩かずにメモリから即座に返せる。これを「バッファヒット」と呼ぶ。チューニングの極意は、いかにして「ディスクへのアクセスを減らし、バッファヒット率を上げるか」に尽きるわけだ。

2. なぜ共有バッファのサイズ設定が重要なのか

PostgreSQLの `postgresql.conf` を見ると、デフォルトではかなり控えめなサイズになっていることが多い。これは、どんな環境でもとりあえず動くようにという配慮なんだけど、本番環境でこれをそのままにするのは「フェラーリのエンジンを軽自動車に積んで走る」ようなものだ。

じゃあ、大きくすればするほどいいのか? そういうわけじゃない。

  • 小さすぎると: 頻繁にディスクI/Oが発生し、CPUは「データの到着待ち」で暇になる(I/O Wait)。
  • 大きすぎると: OSが使えるメモリが減り、OS側のキャッシュ(ページキャッシュ)が圧迫される。また、PostgreSQLの管理コストも増える。

一般的には「搭載メモリの25%程度」が目安と言われるけれど、これはあくまでスタートラインだ。

3. 実践:今のバッファヒット率を計測する

まずは現状把握だ。以下のSQLを叩いてみてほしい。

SELECT
sum(heap_blks_read) as disk_read,
sum(heap_blks_hit) as buffer_hit,
(sum(heap_blks_hit) – sum(heap_blks_read)) / sum(heap_blks_hit + heap_blks_read) 100 as hit_ratio
FROM pg_statio_user_tables;

この `hit_ratio` が99%以上あれば、君のDBはかなり健康だ。逆に90%を切っているなら、共有バッファのサイズを見直すか、インデックスの設計(物理設計)を疑ったほうがいい。

4. 現場の教訓:バッファは「魔法の杖」ではない

ここからが先輩からのアドバイスだ。バッファを増やせばすべて解決すると思ったら大間違いだよ。

  • インデックスなしの全スキャンは無意味:

どんなに共有バッファが巨大でも、インデックスを使わない `SELECT ` を繰り返せば、キャッシュは一瞬で掃き出される(これをキャッシュ汚染と言う)。「バッファが足りないから増やす」前に、「SQLが効率的か」を確認するのが先決だ。

  • OSのキャッシュも味方につける:

PostgreSQLは共有バッファだけでなく、OSレベルのファイルシステムキャッシュも活用する。共有バッファを巨大にしすぎると、OSのキャッシュ領域が削られてしまい、結果的にトータルパフォーマンスが落ちることもある。バランス感覚が大事だ。

最後に:チューニングは「観測」から

もし共有バッファの値を変更するなら、一度に大きく変えちゃダメだ。少しずつ増やして、`pg_stat_activity` や `pg_stat_statements` を見て、実際にクエリの実行時間がどう変化したかをグラフ化する。

エンジニアの仕事は、勘で設定を変えることじゃない。「なぜその設定にしたのか」をデータで説明できるようになることだ。

もし、設定を変えても「バッファヒット率は高いのに遅い」という現象に突き当たったら、次は「ロック待ち」や「チェックポイントの頻度」を疑う番だ。その話はまた今度しよう。

現場からは以上だ。困ったことがあったら、いつでもコードを見せてくれよ。

コメント

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