この記事では、ハードウェアの理想的な同時実行性を計算するために PostgreSQL Wiki によって公開されている式 (エコシステムで最も引用されている 接続プールのサイジング式) を示し、各接続のコストがアプリケーション スレッドよりも高い理由を説明し、推測せずに max_connections を設定する手順を詳しく説明します。私たちの ベンチマーク方法論 は、このブログのパフォーマンスに関する主張に使用される測定プロトコルを文書化しています。
必需品
- プールを使用しない場合、max_connections は Postgres が効率的に並列処理できるものだけでなく、すべての 同時クライアント接続をカバーする必要があります。
- PostgreSQL Wiki の参照式: 理想的なアクティブ同時実行数 = (物理コア × 2) + 効率的なディスク。測定によって検証される開始点であり、厳密な制限ではありません。
- max_connections は
postmasterコンテキスト パラメータです。これを変更するには、単純なリロードではなく、サーバーを完全に再起動する必要があります。 - 各 Postgres 接続は、軽量スレッドではなく、別個のシステム プロセスです。これが、接続数が増加するとすぐにオーバーヘッドが現実のものになる原因です。
- コードで確認: 専用の Postgres クラスタでは、Aurabase はクラスタのサイズに応じて max_connections を 50 (無料層) から 400 (エンタープライズ層) まで変化させます。
Postgres 接続のコストがアプリケーション スレッドよりも高い理由
Postgres は接続に軽量スレッド プールを使用しません。クライアント接続ごとに、本格的なシステム プロセスがトリガーされます。
postmaster プロセスは、接続が試行されるたびに新しいプロセス (「フォーク」) を作成し、セッションが終了するまでこの単一セッション専用になります。公式プロジェクトのドキュメントでは、アーキテクチャの基礎に関する章でこのメカニズムが正確に説明されています (postgresql.org/docs/current/connect-estab.htmlの「接続セマンティクス」セクション、2026 年 8 月 24 日にアクセス)。
この選択には大きな利点があります。1 つの接続でクラッシュしても他の接続には影響せず、各プロセスはサーバーの残りの部分から分離されます。また、直接的なコストもかかります。接続が追加されるたびに、OS プロセス全体がスケジュールに追加され、独自のメモリ空間とカーネルのコンテキスト スイッチング オーバーヘッドが発生します。
プールせずに Postgres への 500 の直接接続を開くアプリケーションでは、2 つのリクエストの間でプロセスの大部分がアイドル状態のままであっても、サーバーは 500 の同時システム プロセスを管理する必要があります。
接続が実際に消費するもの: 共有メモリと work_mem
2 つの異なるメカニズムが記憶に影響を及ぼし、それらを混同するとほとんどの場合誤診につながります。
1つ目は修正されています。 Postgres は起動時に、これらの接続がその後開かれるかどうかに関係なく、max_connections の値に応じたサイズの共有メモリ構造 (ロック、プロセス テーブル) を予約します。この設定の公式ドキュメントでは、この設定を増やすと、OS のデフォルト構成で許可されているよりも多くのシステム共有メモリが必要になる可能性があると明示的に指摘されています (postgresql.org/docs/current/runtime-config-connection.html、2026 年 8 月 24 日にアクセス)。
2 つ目は可変であり、大規模になるとさらに危険です。work_mem は接続ごとに 1 回割り当てられるのではなく、クエリ プランの並べ替えまたはハッシュ操作ごとに 1 回割り当てられます。この点については、公式ドキュメントで明示されています。複雑なクエリではこれらの操作のいくつかを並行して起動でき、複数のセッションで同じことを同時に行うことができるため、実際に使用されるメモリは work_mem の数倍の価値がある可能性があります (postgresql.org/docs/current/runtime-config-resource.html、2026 年 8 月 24 日にアクセス)。
サーバーのメモリを脅かすのは、max_connections × work_mem だけではありません。これは、max_connections × work_mem × クエリごとの同時操作の数です。この製品は、無害であると考えられる max_connections の増加後にスワップするサーバー、またはメモリ不足になるサーバーについて説明します。
PostgreSQL Wiki のサイジング公式
公式 PostgreSQL プロジェクト Wiki には、開いている接続の合計数ではなく、ハードウェアが並行して効率的に処理できるアクティブな 接続 の数を計算するためのベンチマーク式が文書化されています (wiki.postgresql.org/wiki/Number_Of_Database_Connections、2026 年 8 月 24 日にアクセス)。
理想的なアクティブ同時実行数 = (物理コア × 2) + 効率的なディスク。コア数にはハイパースレッディングは含まれません。最新の SSD ストレージでは、有効なディスクの数は 1 に近いままであり、独立した物理ディスク (「スピンドル」) の概念は本来の意味をほとんど失っています。
8 つの物理コアと SSD ストレージを備えたサーバーでは、式により、スループットが低下し始めるまでに、(8 × 2) + 1 = 17 のアクティブな接続が得られます。この数字はしばしば驚くべきものであり、アプリケーションが実際に開く数百の接続に比べれば、非常に小さいように見えます。これはまさに次の段落の主題です。
式によって計算される数値は、アプリケーションが開く必要があるクライアント接続の数ではなく、CPU とディスクが吸収できる同時実行性を測定します。 20 個のアプリケーション プロセスからなるフリートは、それぞれが 10 個の接続の独自のプールを持ち、たとえ特定の時点でアクティブに動作しているのが 17 個だけであっても、Postgres への同時接続を 200 個開きます。プーラーがない場合、max_connections は 17 ではなく 200 をカバーする必要があります。このギャップこそが、たとえどれを選択することになるとしても、ほとんどのアーキテクチャーで プーラーをトランザクション モードに追加することを促すのです (の PgBouncer、Supavisor、および PgCat の比較を参照してください)。
max_connections を変更する方法 (および再起動が必要な理由)
max_connections はホットスワップされません。これは postmaster コンテキスト パラメータです。Postgres は起動時にこれを 1 回読み取り、共有メモリのサイズを設定します。構成のリロード (pg_reload_conf() または SIGHUP) だけでは十分ではないため、サーバーを再起動する必要があります。
まず現在の値とそのコンテキストをチェックして、再起動が必要かどうかを確認します。
次に、新しい値を適用して、再起動します。
max_connections には、デフォルトで superuser_reserved_connections (デフォルトでは 3) が含まれます。これらの接続は、飽和状態になった場合に備えてスーパーユーザー用に予約されており、グローバル カウンタにまだ到達していない場合でも、アプリケーションでは決して使用できません。
Aurabase が Postgres クラスタで max_connections を割り当てる方法
max_connections のサイズ設定は、単なる理論的な作業ではありません。 Aurabase が管理対象 Postgres クラスターに予算を割り当てる方法は次のとおりです。
専用クラスター: プロジェクトごとに 1 つの Postgres クラスター
このレベルでは (専用と共有ベースのの比較を参照)、各プロジェクトは、インスタンスのサイズに合わせてサイズ設定された独自の CloudNativePG クラスターと独自の max_connections バジェットを受け取ります。
| 無料(専用) | 最大接続数 50 | 1 インスタンス · 500m vCPU · 512Mi |
|---|---|---|
| プロ (デフォルト) | 最大接続数 200 | 2 インスタンス · 1 vCPU · 2Gi |
| チーム | 最大接続数 300 | 3 インスタンス · 2 vCPU · 3Gi |
| ビジネス | 最大接続数 400 | 3 インスタンス · 2 vCPU · 4Gi |
共有クラスター: 組織の複数のプロジェクト、共有予算
この 2 番目のパスでは、同じ組織のすべてのプロジェクトが、共有プライマリの前にある CNPG プーラー (PgBouncer、transactionモード) を介して接続します。
| 無料 | 最大接続数 50 | max_client_conn 100 | 最大ユーザー接続数 20 |
|---|---|---|---|
| プロ | 最大接続数 100 | max_client_conn 200 | 最大ユーザー接続数 60 |
| チーム | 最大接続数 200 | max_client_conn 400 | 最大ユーザー接続数 150 |
組織内のすべてのプロジェクトは、共有アプリケーション ロールを通じて接続します。 したがって、max_user_connections だけで、このロールがクラスター全体で開くことができるサーバー接続の合計に上限が設定されます。これは、プーラー自体へのクライアント接続のみを制限する max_client_connではなく、実際のクラスター全体の安全策です。
ただし、このプーラーは SDK アプリケーション トラフィックのみを処理します。 PostgREST に関しては、プライマリ (-rwサービス) に直接接続されたままになります。トランザクション モードでプールすると、 pgrstという名前の専用 LISTEN チャネルをリッスンするスキーマ リロード メカニズムが壊れます。したがって、独自の接続 (共有レベルのレプリカごとに 2、専用レベルのレプリカごとに 10) は、プーラーの外部でプライマリの max_connections バジェットに直接カウントされます。これは、まさに、以下の手順のステップ 1 で含める必要がある種類の「忘れられた」接続です。
コードでは、これらの共有プーラー バジェットを、公開されたベンチマークからの固定数値としてではなく、負荷下で pg_stat_activity を測定することによって、実際の条件で調整される開始値として明示的に文書化します。これは、ベンチマーク方法論で説明されているものと同じ規律です。推測して期待するのではなく、調整する前に測定します。これらのクラスターは PostgreSQL 16 で実行されます。この選択は、Postgres 16 対 17 対 18の比較に記載されています。
プールせずに max_connections のサイズを変更する 5 ステップの手順
この手順は特定のツールには依存しません。管理対象または自己ホスト型の任意の Postgres サーバーに適用されます。
- 実際のクライアント接続をカウントします。 アプリケーション プロセスの数に内部プールのサイズを掛けたものに、管理ツール、レプリケーション、監視を加えたもの。 max_connections の下限を設定するのは、式ではなくこの数値です。
- PostgreSQL wiki の式 (物理コア × 2) + 効率的なディスクを使用して、ハードウェアの理想的な同時実行性 を計算します。この図は、スループットを低下させることなく、これらの接続のうち実際にいくつが並行して動作できるかを示しています。
- max_connections を手順 1 で実際に必要な値よりも大きく設定し、
superuser_reserved_connectionsおよびアプリケーションの外部で独自の接続を開く管理ツール用に余裕を持たせます。 - ALTER SYSTEM SET を使用して変更を適用し、サーバーを再起動します。 これはポストマスター パラメータです。上で詳しく説明したように、単純なリロードでは十分ではありません。
- pg_stat_activity を経時的に監視します。 アイドル状態の接続の数がアクティブな接続の数を大幅に超えている場合、これは max_connections の問題ではありません。これは、より大きな数ではなく、サーバーの前にプーラーが必要であることを示しています。
ステップ 5 のモニタリング リクエストは、直接使用できます。
フォーミュラではもう十分ではないとき: プーラーが必要な兆候
max_connections だけでは十分ではなくなった場合、その値に関係なく、体系的に 3 つのシグナルが返されます。
FATAL: sorry, too many clients alreadyエラーはピーク負荷時に表示されますが、pg_stat_activityによって表示される接続の大部分はアイドル状態です。- アプリケーションはサーバーレス環境または一時的なワーカー (エッジ機能、短いジョブ) で実行され、Postgres の接続ごとのプロセス モデルが対応できるように設計されているよりもはるかに高速に接続を開いたり閉じたりします。
- 上記の式と手順はすでに適用されており、クライアント接続の実際の必要性は、work_mem やshared_buffers を危険にさらすことなく利用可能なメモリが割り当てることができる量を超え続けています。
これら 3 つのケースでは、ほとんどの場合、正しい答えは、より高い max_connections ではなく、アプリケーションと Postgres の間に位置するプーラーです。 の PgBouncer、Supavisor、および PgCat の比較 では 3 つのオプションについて詳しく説明しており、トランザクション モードの ガイド では、プーラーが導入された後の最も一般的な妥協について説明しています。接続以外のすべての Postgres チューニングについては、 実稼働 Postgres チューニング チェックリストを参照してください。