変更要約: 初版(主題G3・G3.1〜G3.2)
3.1性能に関係するパラメータ
PostgreSQLの主要な性能パラメータを学びます。メモリ系のshared_buffers・huge_pages・work_mem・maintenance_work_mem、WAL/チェックポイント系のwal_level・fsync・checkpoint_timeout・max_wal_size・wal_keep_size・checkpoint_completion_target、ロック系のdeadlock_timeout、そしてプランナ・統計・リソース使用に関わるパラメータの相互作用を押さえます。
PostgreSQLの性能パラメータは単独で効くものが少なく、メモリ・ディスクI/O・WAL書き込みが互いに影響し合うため、1つを変えると別の挙動が変わることがよくあります。Gold試験では個々のパラメータの意味だけでなく、「なぜその既定値なのか」「変更すると何と何が連動するか」という相互作用の理解が問われます。
3.1.1メモリ関連パラメータ
- shared_buffers=PostgreSQLがOSキャッシュとは別に確保する専用共有バッファのサイズ。既定は控えめ(多くの環境で128MB相当)で、実務では物理メモリの25%程度を起点に調整するのが定石。大きくしすぎるとOSキャッシュとの二重キャッシュで無駄が生じ、変更にはサーバ再起動が必要(設定変更カテゴリが
postmaster)。 - huge_pages=Linuxのヒュージページ(既定4KBより大きい2MB等の単位でメモリ管理)を
shared_buffers用に使うかの設定(try/on/off)。ページテーブルエントリ数を減らしTLBミスを抑えることで大規模shared_buffers環境の性能を底上げするが、事前にOS側でヒュージページを確保しておく必要があり、確保不足だとon指定では起動失敗、try(既定)なら通常ページへフォールバックする。 - work_mem=ソート・ハッシュ結合・ハッシュ集約など、クエリ内の1つの操作が使える作業メモリの上限。既定は小さめ(4MB相当)で、同時実行クエリ数×クエリあたりの操作数だけ乗算的に消費されうるため、闇雲に大きくするとメモリ枯渇を招く。不足するとディスク上の一時ファイルにスピル(
log_temp_filesで検出可能)し性能劣化する。 - maintenance_work_mem=VACUUM・CREATE INDEX・ALTER TABLE ADD FOREIGN KEYなどの保守作業が使える作業メモリの上限(既定64MB相当)。
work_memより大きく設定するのが定石(保守作業は同時実行数が少なく、大きなメモリを一時的に使うほど高速化する)。特にVACUUMのデッド行ID保持やインデックス構築のソートで効果が大きい。
3.1.2WAL・チェックポイント・ロック関連パラメータ
- wal_level=WALに記録する情報量(
minimal/replica/logical)。レプリケーションを使うならreplica以上、ロジカルレプリケーションならlogicalが必須。minimalはスタンドアロン向けでWAL量が最少だが、アーカイブ/レプリケーション用途には使えない。既定はreplica。 - fsync=WALやデータファイルへの書き込みをOSに確実にディスクへ同期させるか(既定
on)。offにすると書き込みが速くなるが、クラッシュ時にデータ破損の危険があり本番では変更禁止(大量初期ロード時に一時的に外す運用はあるが、完了後は必ず戻す)。 - checkpoint_timeout=チェックポイントの最大間隔(既定5分)。max_wal_size=チェックポイントをトリガーするWAL量の上限(既定1GB)。どちらか早く到達した方でチェックポイントが発生する。頻繁すぎるチェックポイントはI/O負荷を上げるため、書き込みの多い環境では両方を伸ばすのが定石(例:
checkpoint_timeout=15min・max_wal_size=4GB)。 - checkpoint_completion_target=チェックポイントの書き込みを次のチェックポイントまでの間隔に対してどれだけの割合でならして完了させるか(PostgreSQL 14 の既定0.9/12・13 の既定0.5)。1に近いほどI/Oが平滑化されスパイクが減るが、次のチェックポイントとの間隔が詰まりすぎない範囲で設定する。wal_keep_size=スタンバイに送る前のWALセグメントを最低限保持しておくサイズ(レプリケーション遅延時の欠落防止・既定0=無制限保持なし)。
- deadlock_timeout=ロック待ちがデッドロック検査を発動するまで待つ時間(既定1秒)。短くしすぎると通常の混雑を誤ってデッドロックと疑い検査コストが増え、長すぎるとデッドロック検出が遅れてクライアントの応答が悪化する。デッドロック自体は稀な事象という前提で既定値は控えめな頻度に調整されている。
「shared_buffersは変更にサーバ再起動が必要(既定は控えめ・目安は物理メモリの25%程度)」「work_memは操作単位・同時実行数で乗算的に消費されるため大きくしすぎ注意」「maintenance_work_memはVACUUM/CREATE INDEX用でwork_memより大きめが定石」「チェックポイントはcheckpoint_timeoutとmax_wal_sizeのどちらか早い方で発生」「wal_levelはレプリケーションに応じてreplica/logicalを選ぶ」「fsync=offは本番厳禁」が最頻出です。パラメータ名と役割・既定値・相互作用(何と何が連動するか)の対応を正確に押さえましょう。
実際のチューニング判断では、パラメータ同士の因果の連鎖を追うことが重要です。例えば「バッチ処理のバルクロードで書き込みが遅い」という相談を受けたとしましょう。まず疑うべきはチェックポイントの頻発です。大量のINSERTでWALが急速に積み上がるとmax_wal_sizeにすぐ到達し、既定の1GBでは短い間隔で何度もチェックポイントが走ってI/Oスパイクが発生します。ここでmax_wal_sizeを4GBや8GBへ広げ、checkpoint_completion_targetを0.9のまま維持(または環境によりさらに調整)すれば、チェックポイントの頻度と1回あたりの書き込み集中を同時に緩和できます。次に、大量データのCOPYやINSERTではmaintenance_work_memではなくwork_memが効くソート処理を伴うインデックス更新が絡む場面もあるため、両者を混同しないことが肝心です。一方で「バルクロード完了後にVACUUM ANALYZEが遅い」という相談なら、疑うべきはmaintenance_work_mem不足です。デフォルトの64MBでは大規模テーブルのデッドタプルID一覧を保持しきれず複数パスに分割されるため、セッション単位でSET maintenance_work_mem = '1GB'のように一時的に引き上げてから実行する運用が定石です。また、shared_buffersを安易に大きくしても、OSページキャッシュとの二重キャッシュで必ずしも性能が上がるとは限らず、effective_cache_size(プランナへ「OSキャッシュ込みでどれだけ使えるか」を伝える値)と合わせて検討する必要があります。ロック関連では、deadlock_timeoutを極端に短くして「デッドロックを早期発見したい」という発想は逆効果になりがちで、通常のロック待ちまで頻繁にデッドロック検査コストを払う羽目になります。むしろデッドロックの頻発自体はアプリケーション側のロック取得順序の問題であることが多く、パラメータ調整より先にロック取得順序を揃える設計変更を検討すべき場面です。
| パラメータ | 役割 | 注意点 |
|---|---|---|
| shared_buffers | 専用共有バッファサイズ | 変更に再起動要・目安25% |
| work_mem | 操作単位の作業メモリ上限 | 同時実行数で乗算的に消費 |
| maintenance_work_mem | VACUUM/CREATE INDEX用メモリ上限 | work_memより大きめが定石 |
| max_wal_size / checkpoint_timeout | チェックポイント発生条件 | 早い方でチェックポイント発生 |
ひっかけ: 「work_mem を大きくすれば常に性能が上がる」は誤りです。work_mem は同時実行クエリ数×操作数で乗算的に消費されるため、大きくしすぎるとむしろメモリ枯渇やスワップで性能が悪化します。また「fsync を off にすれば安全にデータベースを高速化できる」も誤り=クラッシュ時のデータ破損リスクを伴う設定で本番運用では原則使いません。「shared_buffers はSET文で即座に変更できる」も誤り=postmasterコンテキストのためサーバ再起動が必要です。
3.1.3この節のまとめ
- メモリ=shared_buffers(再起動要・目安25%)/work_mem(操作単位・乗算消費に注意)/maintenance_work_mem(VACUUM等・work_memより大きめ)/huge_pages(OS側事前確保が前提)
- チェックポイントはcheckpoint_timeoutとmax_wal_sizeの早い方で発生・checkpoint_completion_targetでI/Oを平滑化。wal_levelはレプリケーション要件で選択・fsync=offは本番厳禁。deadlock_timeoutは短すぎ厳禁
進捗の記録にはログインが必要です。
理解度チェック
(軽い確認用)Q1. バッチ処理による大量INSERTの実行中、頻繁なチェックポイントが原因とみられるI/Oスパイクが発生している。まず見直すべきパラメータの組み合わせとして最も適切なのは?
Q2. 大規模テーブルに対する VACUUM ANALYZE が既定設定のままでは非常に遅い。セッション単位で調整すべき最も適切なパラメータは?
Q3. ロジカルレプリケーションを構成する予定のサーバで、wal_level の設定として適切なのはどれか?

