Naast het besparen van de overhead van connect &disconnect waar dit anders bij elk verzoek wordt gedaan, kan een pooler voor verbindingen een groot aantal clientverbindingen naar een klein aantal daadwerkelijke databaseverbindingen leiden. In PostgreSQL ligt het optimale aantal actieve databaseverbindingen meestal ergens rond ((2 * core_count) + Effective_spindle_count) . Boven dit aantal worden zowel de doorvoer als de latentie slechter.
Soms zeggen mensen:"Ik wil 2000 gebruikers ondersteunen, met een snelle responstijd." Het is vrijwel gegarandeerd dat als je dat probeert te doen met 2000 daadwerkelijke databaseverbindingen, de prestaties verschrikkelijk zullen zijn. Als je een machine hebt met vier quad-coreprocessors en de actieve dataset volledig in de cache is opgeslagen, zul je veel betere prestaties zien voor die 2000 gebruikers door de verzoeken door ongeveer 35 databaseverbindingen te leiden.
Om te begrijpen waarom dat waar is, zou dit gedachte-experiment moeten helpen. Overweeg een hypothetische databaseservermachine met slechts één bron om te delen:een enkele kern. Deze kern verdeelt de tijd gelijkmatig over alle gelijktijdige verzoeken zonder overhead. Laten we zeggen 100 verzoeken die allemaal op hetzelfde moment binnenkomen, die elk een seconde CPU-tijd nodig hebben. De kern werkt op ze allemaal, waarbij ze in de tijd snijden totdat ze allemaal 100 seconden later klaar zijn. Overweeg nu wat er gebeurt als u een verbindingspool vooraan plaatst die 100 clientverbindingen accepteert, maar slechts één verzoek tegelijk doet aan de databaseserver, waarbij verzoeken die binnenkomen terwijl de verbinding bezet is, in een wachtrij worden geplaatst. Als er nu 100 verzoeken tegelijkertijd binnenkomen, krijgt één klant binnen 1 seconde een reactie; een ander krijgt een reactie in 2 seconden en de laatste klant krijgt een reactie in 100 seconden. Niemand hoefde langer te wachten om een reactie te krijgen, de doorvoer is hetzelfde, maar de gemiddelde latentie is 50,5 seconden in plaats van 100 seconden.
Een echte databaseserver heeft meer bronnen die parallel kunnen worden gebruikt, maar hetzelfde principe geldt:als ze eenmaal verzadigd zijn, doe je dingen alleen maar pijn door meer gelijktijdige databaseverzoeken toe te voegen. Het is eigenlijk erger dan het voorbeeld, want met meer taken heb je meer taakwisselingen, meer strijd om vergrendelingen en cache, L2- en L3-cacheregelconflicten en vele andere problemen die zowel de doorvoer als de latentie verminderen. Bovendien, terwijl een hoge work_mem
instelling kan een query op een aantal manieren helpen, die instelling is de limiet per planknooppunt voor elke verbinding , dus met een groot aantal verbindingen moet u dit zeer klein laten om te voorkomen dat de cache wordt leeggemaakt of zelfs tot swapping leidt, wat leidt tot langzamere plannen of zaken als hash-tabellen die naar de schijf worden gemorst.
Sommige databaseproducten bouwen effectief een verbindingspool in de server, maar de PostgreSQL-gemeenschap heeft het standpunt ingenomen dat aangezien de beste verbindingspooling dichter bij de clientsoftware wordt gedaan, ze het aan de gebruikers zullen overlaten om dit te beheren. De meeste poolers hebben een manier om de databaseverbindingen te beperken tot een vast nummer, terwijl ze meer gelijktijdige clientverzoeken toestaan, en ze indien nodig in de wachtrij plaatsen. Dit is wat je wilt, en het moet worden gedaan op een transactionele basis, niet per verklaring of verbinding.