PostgreSQL kan vrij goed verticaal schalen. Hoe meer bronnen (CPU, geheugen, schijf) u beschikbaar kunt stellen aan uw PostgreSQL-server, hoe beter deze kan presteren. Hoewel sommige delen van Postgres automatisch gebruik kunnen maken van de toegenomen bronnen, moeten andere delen configuratiewijzigingen ondergaan voordat verbeteringen kunnen worden opgemerkt.
Lees verder voor meer informatie over hoe u ervoor kunt zorgen dat PostgreSQL volledig gebruik maakt van het systeem waarop u het gebruikt.
CPU
Wat automatisch wordt geschaald
PostgreSQL heeft een traditionele procesarchitectuur, bestaande uit een masterproces (de postmaster genoemd) ) dat een nieuw proces voortbrengt (eenbackend genoemd) ) voor elke nieuwe clientverbinding. Dit betekent dat als er meer CPU-cores beschikbaar zijn, er meer processen tegelijkertijd kunnen worden uitgevoerd, en daarom hoeven backends niet zoveel te strijden voor CPU-beschikbaarheid. CPU-gebonden zoekopdrachten worden sneller voltooid.
Mogelijk wilt u de maximaal toegestane gelijktijdige verbindingen aanpassen op het niveau van het hele systeem, per database of per gebruiker:
-- system level
ALTER SYSTEM SET max_connections = 200;
-- database level
ALTER DATABASE dbname CONNECTION LIMIT 200;
-- user level
ALTER ROLE username CONNECTION LIMIT 20;
zodat malafide apps niet te veel verbindingen kunnen krijgen.
Wat moet worden aangepast
De PostgreSQL-server kan een proces spawnen om huishoudelijke taken uit te voeren, zoals stofzuigen, replicatie, abonnementen (voor logische replicatie) enz. Het aantal van dergelijke werkers wordt niet dynamisch bepaald, maar gewoon ingesteld via configuratie en standaard ingesteld op 8.
De configuratie-instelling op het hoogste niveau voor het aantal werkprocessen is:
# typically specified in postgresql.conf
max_worker_processes = 16
Deze waarde verhogen kan resulteren in een snellere onderhoudstaken, parallelle query's en het maken van indexen.
Parallelle zoekopdrachten
Vanaf versie 9.6 kan Postgres query's parallel uitvoeren als de queryplanner besluit dat dit helpt. Parallelle bevraging omvat het spawnen van arbeiders, het verdelen van werk onder hen en het verzamelen (verzamelen) van de resultaten. Onderworpen aan de algemene limiet van max_worker_processes
eerder ingesteld, zal Postgres bepalen hoeveel werkers kunnen worden voortgebracht voor parallelle zoekopdrachten, afhankelijk van de waarde van twee configuratie-instellingen:
# the maximum number of workers that the system can
# support for parallel operations
max_parallel_workers = 8
# the maximum number of workers that can be started
# by a single Gather or Gather Merge node
max_parallel_workers_per_gather = 8
Als u inactieve CPU's en parallelliseerbare zoekopdrachten hebt, kan het verhogen van deze waarden dergelijke zoekopdrachten versnellen.
Aanmaken van parallelle indexen
In Postgres 11 is ondersteuning toegevoegd voor het parallel maken van B-Tree-indexen. Als u regelmatig B-Tree-indexen maakt of ze REINDEX maakt, kan het helpen deze waarde te verhogen:
# the maximum number of parallel workers that can be
# started by a single utility command
max_parallel_maintenance_workers = 8
Hierdoor kan Postgres deze vele werkers voortbrengen (onder voorbehoud van de algemene limiet van max_worker_processes
) om het maken van B-Tree-indexen te versnellen.
Logische replicatie
Logische replicatie (beschikbaar in Postgres 10 en hoger), vertrouwt op werkprocessen aan de abonnementszijde om wijzigingen van de uitgever op te halen. Door Postgres te vragen om meer logische replicatiewerkers te maken, kunnen de wijzigingen worden opgehaald en parallel worden toegepast, vooral als er meer tabellen zijn. Deze configuratie-instelling verhoogt het totale aantal replicatiewerkers:
# maximum number of logical replication workers
max_logical_replication_workers = 8
Bij streamingreplicatie kunt u een synchronisatie starten met een basisback-up. Voor logische replicatie moeten wijzigingen echter via het replicatieprotocol zelf, over het netwerk, worden ingevoerd. Dit kan tijdrovend zijn. Door meer werknemers toe te staan tijdens de synchronisatiefase kan dit proces worden versneld:
# basically the number of tables that are synced in
# parallel during initialization of subscription
max_sync_workers_per_subscription = 8
Autovacuüm
Af en toe zal Postgres, op basis van een aantal configuratie-instellingen, een heleboel werkers voortbrengen die de databasetabellen VACUMEREN. Dit heet natuurlijk autovacuüm, en het aantal werkers dat de autovacuum launcher elke keer spawnt, kan worden ingesteld via de configuratie-instelling:
# the maximum number of autovacuum processes
autovacuum_max_workers = 8
WAL-compressie
Als u CPU over heeft, kunt u de CPU inruilen voor schijfbandbreedte door de pagina's die naar de WAL-bestanden worden geschreven te comprimeren. Dit vermindert de hoeveelheid gegevens die naar schijf moet worden geschreven, ten koste van meer CPU-cycli om de gegevens te comprimeren. Het vermindert ook de hoeveelheid gegevens die over de draad moeten worden verzonden voor streamingreplicatie.
In de praktijk zijn de voordelen van WAL-compressie de zeer redelijke overhead zeker waard. Om het aan te zetten, gebruik:
# compresses full page images written to WAL
wal_compression = on
Geheugen
Wat automatisch wordt geschaald
Het besturingssysteem beheert en gebruikt automatisch geheugen dat niet door een toepassing wordt gebruikt voor het cachen van gegevens die recentelijk zijn gelezen van en geschreven naar de schijf. Dit versnelt schijfintensieve applicaties enorm, en zeker PostgreSQL.
In Linux, de meest populaire host voor Postgres, kan de grootte van de schijfcache van het besturingssysteem niet door de gebruiker worden ingesteld. Het beheer is intern voor Linux. Onder geheugendruk zal het schijfcachegeheugen vrijgeven aan applicaties.
Wat moet worden aangepast
Queryplanner
De queryplanner moet de hoeveelheid schijfcache die door het besturingssysteem wordt geleverd als factor in zijn schattingen opnemen. Als het je is gelukt om de schijfcache van het besturingssysteem aanzienlijk te vergroten (door het beschikbare geheugen te vergroten), kan het verhogen van deze configuratie-instelling helpen bij het verbeteren van de schattingen van de planner:
# the planner's assumption about the effective size
# of the disk cache that is available to a single query.
effective_cache_size = 64GB
Gedeeld geheugen
PostgreSQL gebruikt een set buffers die wordt gedeeld tussen alle werkers en backend-processen. Dit worden gedeelde buffers genoemd , en de hoeveelheid geheugen toegewezen voor gedeelde buffers wordt ingesteld met behulp van de configuratie-instelling:
shared_buffers = 32GB
Tijdelijke buffers
Wanneer tijdelijke tabellen worden benaderd door een query, worden buffers toegewezen om de ingelezen inhoud in de cache op te slaan. De grootte van deze buffer wordt ingesteld met behulp van de configuratie-instelling:
# the maximum number of temporary buffers used
# by each database session
temp_buffers = 100MB
Als u geheugen over heeft en query's die veel tijdelijke tabellen gebruiken, kan het verhogen van deze waarde dergelijke query's versnellen.
Werkgeheugen
Werkgeheugen wordt lokaal en privé toegewezen door backends. Het wordt gebruikt om sorteringen en samenvoegingen uit te voeren zonder dat u tijdelijke tabellen hoeft te maken. Als u dit verhoogt van de standaardwaarde van 4 MB, kunnen query's sneller worden voltooid tijdens het maken van tijdelijke tabellen:
# the amount of memory to be used by internal sort
# operations and hash tables before writing to temporary disk files
work_mem = 16MB
Onderhoudswerkzaamheden
Het geheugen dat wordt gebruikt door VACUUM, het maken van indexen en andere dergelijke onderhoudsopdrachten worden beheerd door de configuratie-instelling maintenance_work_mem
. Als u dit bedrag verhoogt, kunnen deze bewerkingen worden versneld, vooral bij indexen of tabellen die opnieuw moeten worden gemaakt.
Het geheugen dat door de autovacuümwerkers wordt gebruikt, kan uit het onderhoudswerkgeheugen worden gehaald (door autovacuum_work_mem = -1
in te stellen ) of onafhankelijk geconfigureerd.
# the maximum amount of memory to be used by
# maintenance operations
maintenance_work_mem = 128MB
# maximum amount of memory to be used by each
# autovacuum worker process
autovacuum_work_mem = -1
Schijf
Wat automatisch wordt geschaald
Schijven kunnen groter, sneller of meer gelijktijdig worden gemaakt. De grootte van de schijf is het enige waarover PostgreSQL geen instructies hoeft te krijgen. Standaard zal PostgreSQL zichzelf niet beperken in het gebruik van beschikbare schijfruimte. Dit is meestal prima.
Je kunt echter een limiet stellen aan de totale grootte van tijdelijke bestanden die zijn gemaakt, om een zekere mate van bescherming te bieden tegen zoekopdrachten die proberen een miljard rijen te sorteren en dergelijke:
# the maximum amount of disk space that a process
# can use for temporary files
temp_file_limit = 500GB
Wat moet worden aangepast
Concurrency
RAID-ed schijven en bestandssystemen zoals ZFS kunnen worden ingesteld om meer gelijktijdigheid te ondersteunen. Dat wil zeggen, u kunt een paar schijflees-/schrijfbewerkingen tegelijkertijd laten uitvoeren door dergelijke bestandssystemen vanwege de manier waarop de gegevens intern worden opgeslagen of verwerkt.
U kunt Postgres meerdere gelijktijdige schijf-I/O laten uitgeven door deze configuratie-instelling te gebruiken:
# the number of concurrent disk I/O operations that
# PostgreSQL expects can be executed simultaneously
effective_io_concurrency = 4
Dit wordt momenteel echter alleen gebruikt door bitmap-heapscans.
Willekeurige paginakosten
De queryplanner van Postgres gaat ervan uit dat sequentiële reads sneller zijn dan randomreads. Hoeveel sneller is een waarde die u precies kunt aanpassen. Standaard gaat het ervan uit dat willekeurige uitlezingen 4 keer duurder zijn.
Afhankelijk van uw schijfconfiguratie, werkbelasting en benchmarking, als u zeker weet dat willekeurige uitlezingen slechts twee keer zo duur zijn als sequentiële leesbewerkingen, kunt u dat aan Postgres vertellen:
# the planner's estimate of the cost of a disk page
# fetch that is part of a series of sequential fetches
seq_page_cost = 1
# the planner's estimate of the cost of a
# non-sequentially-fetched disk page
random_page_cost = 2
Tablespaces
Om voordeel te halen uit meerdere schijven die niet als één groot enkel bestandssysteem zijn gemount, kun je tablespaces gebruiken. Met tablespaces kun je tabellen plaatsen of verschillende bestandssystemen indexeren. Dit kan de gelijktijdigheid verbeteren en biedt een gemakkelijke manier om tafelgroei aan te pakken.
CREATE TABLESPACE disk2 LOCATION '/mnt/disk2/postgres';
Lees hier meer over tablespaces.
Netwerk
Netwerk is meestal de minst gebruikte bron op een PostgreSQL-server en is zelden verzadigd. Als je toch moet schalen, is het eenvoudig genoeg om meer netwerkinterfaces toe te voegen, elk met hun eigen IP, en PostreSQL op ze allemaal te laten luisteren:
listen_addresses = '10.1.0.10,10.1.0.11'
De clients moeten load-balanced zijn over alle IP's waarop Postgresluistert.
Anders
Er zijn een paar andere configuratie-instellingen die kunnen worden aangepast, waarvan de meeste meer CPU gebruiken en geheugen.
Partitionwise-bewerkingen
Postgres 10 introduceerde tabelpartitionering, wat verbeterd is in Postgres 11. Sommige query-optimalisaties op partities zijn niet standaard ingeschakeld, omdat ze kunnen resulteren in een hoger CPU- en geheugenverbruik. Dit zijn:
# allow a join between partitioned tables to be
# performed by joining the matching partitions
enable_partitionwise_join = on
# allow grouping or aggregation on a partitioned
# tables performed separately for each partition
enable_partitionwise_aggregate = on