sql >> Database teknologi >  >> RDS >> PostgreSQL

Hvordan hjælper pgBouncer med at sætte fart på Django

Udover at gemme overheaden for tilslutning og afbrydelse, hvor dette ellers gøres på hver anmodning, kan en forbindelsespooler kanalisere et stort antal klientforbindelser ned til et lille antal faktiske databaseforbindelser. I PostgreSQL er det optimale antal aktive databaseforbindelser normalt et sted omkring ((2 * core_count) + effective_spindle_count) . Over dette tal bliver både gennemløb og latenstid værre.

Nogle gange vil folk sige "Jeg vil gerne støtte 2000 brugere med hurtig responstid." Det er stort set garanteret, at hvis du prøver at gøre det med 2000 faktiske databaseforbindelser, vil ydeevnen være forfærdelig. Hvis du har en maskine med fire quad-core processorer, og det aktive datasæt er fuldt cachelagret, vil du se meget bedre ydeevne for disse 2000 brugere ved at sende anmodningerne gennem omkring 35 databaseforbindelser.

For at forstå, hvorfor det er sandt, burde dette tankeeksperiment hjælpe. Overvej en hypotetisk databaseservermaskine med kun én ressource at dele - en enkelt kerne. Denne kerne vil tidsdele ens mellem alle samtidige anmodninger uden overhead. Lad os sige, at 100 anmodninger alle kommer ind på samme tidspunkt, som hver har brug for et sekunds CPU-tid. Kernen virker på dem alle og opdeles mellem dem, indtil de alle er færdige 100 sekunder senere. Overvej nu, hvad der sker, hvis du sætter en forbindelsespulje foran, som accepterer 100 klientforbindelser, men kun laver én anmodning ad gangen til databaseserveren, og sætter eventuelle anmodninger, der ankommer, mens forbindelsen er optaget, i en kø. Når nu 100 anmodninger ankommer på samme tid, får en klient et svar på 1 sekund; en anden får et svar på 2 sekunder, og den sidste klient får et svar på 100 sekunder. Ingen behøvede vente længere for at få et svar, gennemløbet er det samme, men den gennemsnitlige latenstid er 50,5 sekunder i stedet for 100 sekunder.

En rigtig databaseserver har flere ressourcer, som kan bruges parallelt, men det samme princip gælder, når de først er mættede, skader du kun tingene ved at tilføje flere samtidige databaseanmodninger. Det er faktisk værre end eksemplet, for med flere opgaver har du flere opgaveskift, øget indhold for låse og cache, L2- og L3-cachelinjekonflikt og mange andre problemer, der skærer i både gennemløb og latency. Oven i det, mens en høj work_mem indstilling kan hjælpe en forespørgsel på en række måder, denne indstilling er grænsen pr. plannode for hver forbindelse , så med et stort antal forbindelser skal du lade dette være meget lille for at undgå at tømme cache eller endda føre til ombytning, hvilket fører til langsommere planer eller sådanne ting som hashtabeller, der spildes til disken.

Nogle databaseprodukter bygger effektivt en forbindelsespulje ind i serveren, men PostgreSQL-fællesskabet har indtaget den holdning, at da den bedste forbindelsespooling udføres tættere på klientsoftwaren, vil de overlade det til brugerne at administrere dette. De fleste poolere vil have en måde at begrænse databaseforbindelserne til et hårdt antal, mens de tillader flere samtidige klientanmodninger end det, og sætter dem i kø efter behov. Dette er, hvad du ønsker, og det skal gøres på en transaktions basis, ikke pr. udsagn eller forbindelse.



  1. SQLite FULD YDRE JOIN-emulering

  2. Forbinder C# til Oracle

  3. Indsæt flere rækker UDEN at gentage INSERT INTO ...-delen af ​​sætningen?

  4. Postgresql vælg indtil et bestemt totalbeløb er nået