接続プーラーは、リクエストごとに行われる接続と切断のオーバーヘッドを節約するだけでなく、多数のクライアント接続を少数の実際のデータベース接続に集中させることができます。PostgreSQL では、アクティブなデータベース接続の最適な数は通常((2 * core_count) + effective_spindle_count) 付近です。この数値を超えると、スループットとレイテンシの両方が悪化します。 注:最近のバージョンでは同時実行性が改善されているため、2022 年には((4 * core_count) + effective_spindle_count)のようなものをお勧めします。
「2000 人のユーザーを迅速な応答時間でサポートしたい」と言う人もいます。2000 の実際のデータベース接続でこれを実行しようとすると、パフォーマンスが大幅に低下することはほぼ確実です。4 つのクアッドコア プロセッサを備えたマシンがあり、アクティブなデータ セットが完全にキャッシュされている場合、約 35 のデータベース接続を介して要求を集めることで、2000 人のユーザーのパフォーマンスが大幅に向上します。
その理由を理解するには、この思考実験が役立つはずです。共有するリソースが 1 つだけ (シングル コア) の仮想データベース サーバー マシンを考えてみましょう。このコアは、オーバーヘッドなしですべての同時リクエスト間で均等にタイム スライスします。100 件のリクエストがすべて同時に到着し、それぞれに 1 秒の CPU 時間が必要だとします。コアはそれらすべてで動作し、100 秒後にすべてが終了するまでそれらの間でタイムスライスします。ここで、100 のクライアント接続を受け入れるが、データベース サーバーに対して一度に 1 つの要求のみを行う接続プールを前に配置し、接続がビジー状態である間に到着するすべての要求をキューに入れるとどうなるかを考えてみましょう。100 個のリクエストが同時に到着すると、1 つのクライアントが 1 秒で応答を受け取ります。もう1つは2秒で応答を取得し、最後のクライアントは 100 秒で応答を受け取ります。応答を得るためにこれ以上待つ必要はありませんでした。スループットは同じですが、平均待ち時間は 100 秒ではなく 50.5 秒です。
実際のデータベースサーバーには、並行して使用できるより多くのリソースがありますが、同じ原則が当てはまります。リソースが飽和すると、同時データベースリクエストを追加することによって問題が発生するだけです。タスクが増えると、タスク スイッチが増え、ロックとキャッシュの競合が増え、L2 と L3 キャッシュ ラインの競合が発生し、スループットとレイテンシの両方に影響を与える他の多くの問題が発生するため、実際には例よりも悪い結果になります。その上、高いwork_mem
設定は多くの点でクエリに役立ちますが、その設定は各接続のプラン ノードごとの制限であるため、多数の接続では、キャッシュのフラッシュやフラッシュを避けるために、これを非常に小さくしておく必要があります。スワッピングにつながることもあり、プランが遅くなったり、ハッシュ テーブルがディスクにあふれたりすることもあります。
一部のデータベース製品は効果的に接続プールをサーバーに組み込みますが、PostgreSQL コミュニティは、最良の接続プールはクライアント ソフトウェアの近くで行われるため、これを管理するのはユーザーに任せるという立場をとっています。ほとんどのプーラーには、データベース接続をハード数に制限する方法がいくつかありますが、それよりも多くの同時クライアント要求を許可し、必要に応じてそれらをキューに入れます。これはあなたが望むものであり、ステートメントや接続ごとではなく、トランザクションごとに行う必要があります。