Aurora PostgreSQL の shared_buffers パラメータ


shared_buffers

shared_buffers は 共有メモリバッファ のメモリ量を設定するPostgreSQL のパラメータ。

PostgreSQL 15 からのデフォルト値は 16,384(それ以前は1,024)。 BLCKSZ は通常 8kB(8192byte) なので、

16,384 * 8,192 = 134,217,728 byte
134,217,728 ÷ 1024 ÷ 1024 = 128 MiB

となり、128 MiB が通常のデフォルト値となる。


shared_buffers の推奨値は、公式ドキュメントによると、1GB 以上のメモリを持つ専用データベースサーバを使用している場合、システムメモリの 25% とされている。

PostgreSQL は OS のキャッシュにも依存するため、shared_buffers の値に 40% 以上を割り当ててもパフォーマンス向上は見込めないとされている。

通常は 25% と考え、データ量がメモリに載る程度で同時接続数などをコントロールできる場合は(40%などの中途半端な値ではなく) 75% などの(OSのキャッシュに頼らない)大きな値を( max_wal_size の増加と合わせて)採用するのが現実的な解となるようである。


Aurora PostgreSQL の shared_buffers

Aurora PostgreSQL ではダブルバッファリングを排除し、ファイルシステムキャッシュを利用しないため、shared_buffers の値は 75% を設定することがベストプラクティスとされている。

実際のデフォルト値は(パラメータグループにて)以下のように定義されている。

SUM( {DBInstanceClassMemory / 12038}, -50003 )

32 GiB (34,360,000,000 byte) インスタンスの shared_buffers の値を確認すると以下のようになっている。

SELECT name, setting, unit, context FROM pg_settings WHERE name = 'shared_buffers';

name          |setting|unit|context   |
--------------+-------+----+----------+
shared_buffers|2698181|8kB |postmaster|

この値は、

2,698,181 * 8,192 = 22,103,498,752 byte
22,103,498,752 ÷ 1024 ÷ 1024 ≒ 21 GiB

shared_buffers として 21 GiB ほど確保していることとなり、インスタンスメモリサイズの(22,103,498,752 ÷ 34,360,000,000) 約65% 程に相当する。

AWS の情報センターには以下のように説明されている。

RDS DB インスタンスの場合、DB パラメータグループでのデフォルト値は合計メモリの 25% に設定されています。Aurora DB インスタンスの場合、DB パラメータグループのデフォルト値は、インスタンスクラスに応じて 50% から 75% の間で設定されます。Aurora PostgreSQL はダブルバッファリングを排除し、ファイルシステムキャッシュを利用しないため、Aurora DB インスタンスのデフォルト値は高くなっています。つまり、Aurora PostgreSQL では shared_buffers を大きくして、パフォーマンスを改善できます。Aurora PostgreSQL を使用する場合は、shared_buffers DB パラメータのデフォルト値には、75% を設定することがベストプラクティスです。この値が小さいと、データページが使用可能なメモリが少なくなるため、Aurora ストレージサブシステムの I/O が増加したときに、パフォーマンスの低下が生じる可能性があります。

「デフォルト値は、インスタンスクラスに応じて 50% から 75% の間で設定され」とあり、以下のパラメータグループ計算式の係数根拠は不明だが、

SUM( {DBInstanceClassMemory / 12,038}, -50,003 )

共有メモリバッファとして確保されるメモリ容量は、概ね以下のような計算になっていると考えられる。

DBInstanceClassMemory × 0.68 - 409,624,576(≒400MiB)

DBInstanceClassMemory の 約68% から 400MiB をオフセットとして差し引いた値のメモリ割り当てとなり、ブロックサイズ(8,192) で割ることで shared_buffers の設定値となる。

つまり、上記パラメータグループの定義式では、最大で68%程度の割り当てとなり、75% の割り当てとなることはない。


DBInstanceClassMemory

先の計算の DBInstanceClassMemory は RDSのインスタンスサイズに応じた値であり、DBインスタンスクラスの合計メモリ量から、RDSプロセスやオペレーティングシステム用に予約されているメモリ量を差し引いた値である。

この値の計算ロジックは公表されていないが、先の shared_buffers の値から逆算することができる。

shared_buffers の値は 2,698,181 であったため、

DBInstanceClassMemory = (2,698,181 + 50,003) * 12,038
33,082,638,992 byte

以下のように 1.3G 程がOSや他プロセス側で予約されているようである(この値は、インスタンスクラスの仕様によって異なる)。

34,360,000,000(32 GiB) - 33,082,638,992 = 1,277,361,008