PostgreSQL kan skalere ret godt lodret. Jo flere ressourcer (CPU, hukommelse, disk), du kan stille til rådighed for din PostgreSQL-server, jo bedre kan den yde. Men mens nogle dele af Postgres automatisk kan gøre brug af de øgede ressourcer, har andre dele brug for konfigurationsændringer, før forbedringer kan bemærkes.
Læs videre for at lære mere om, hvordan du sikrer, at PostgreSQL gør fuld brug af det system, du kører det på.
CPU
Hvad skaleres automatisk
PostgreSQL har en traditionel procesarkitektur, der består af en masterproces (kaldet postmaster ), der afføder en ny proces (kaldet enbackend ) for hver ny klientforbindelse. Det betyder, at hvis der er flere CPU-kerner tilgængelige, kan flere processer køre samtidigt, og derfor behøver backends ikke kæmpe så meget om CPU-tilgængeligheden. CPU-bundne forespørgsler afsluttes hurtigere.
Du ønsker måske at justere de maksimalt tilladte samtidige forbindelser på et systemdækkende niveau, pr. database eller pr. bruger niveau:
-- system level
ALTER SYSTEM SET max_connections = 200;
-- database level
ALTER DATABASE dbname CONNECTION LIMIT 200;
-- user level
ALTER ROLE username CONNECTION LIMIT 20;
så useriøse apps ikke kan ende med at få for mange forbindelser.
Hvad skal justeres
PostgreSQL-serveren kan afføde en proces til at tage sig af husholdningsopgaver, såsom støvsugning, replikering, abonnementer (til logisk replikering) osv. Antallet af sådanne arbejdere bestemmes ikke dynamisk, men indstilles blot via konfiguration og er standard til 8.
Konfigurationsindstillingen på øverste niveau for antallet af arbejdsprocesser er:
# typically specified in postgresql.conf
max_worker_processes = 16
Forøgelse af denne værdi kan resultere i fremskyndelse af vedligeholdelsesjob, parallelforespørgsler og indeksoprettelse.
Parallelle forespørgsler
Fra og med version 9.6 kan Postgres udføre forespørgsler parallelt, hvis queryplanneren beslutter, at det vil hjælpe. Parallel forespørgsel involverer gydning af arbejdere, fordeling af arbejde mellem dem og derefter indsamling (indsamling) af resultaterne. Med forbehold for den overordnede grænse for max_worker_processes
indstillet tidligere, vil Postgres bestemme, hvor mange arbejdere der kan affødes til parallel forespørgsel afhængigt af værdien af to konfigurationsindstillinger:
# 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
Hvis du har inaktive CPU'er og paralleliserbare forespørgsler, kan en forøgelse af disse værdier fremskynde sådanne forespørgsler.
Parallel indeksoprettelse
I Postgres 11 blev understøttelse af parallel oprettelse af B-Tree-indekser tilføjet. Hvis du regelmæssigt opretter B-Tree-indekser eller REINDEX dem, kan en forøgelse af denne værdi hjælpe:
# the maximum number of parallel workers that can be
# started by a single utility command
max_parallel_maintenance_workers = 8
Dette vil tillade Postgres at skabe disse mange arbejdere (underlagt den overordnede grænse for max_worker_processes
) for at fremskynde oprettelsen af B-Tree-indekser.
Logisk replikering
Logisk replikering (tilgængelig i Postgres 10 og nyere) er afhængig af arbejdsprocesser på abonnementssiden for at hente ændringer fra udgiveren. Ved at bede Postgres om at skabe flere logiske replikeringsarbejdere, kan ændringerne hentes og anvendes parallelt, især hvis der er flere tabeller. Denne konfigurationsindstilling øger det samlede antal replikeringsarbejdere:
# maximum number of logical replication workers
max_logical_replication_workers = 8
I streaming-replikering kan du starte en synkronisering med en basis backup. For logisk replikering skal ændringer dog trækkes ind via selve replikeringsprotokollen over netværket. Dette kan være tidskrævende. At tillade flere medarbejdere under synkroniseringsfasen kan fremskynde denne proces:
# basically the number of tables that are synced in
# parallel during initialization of subscription
max_sync_workers_per_subscription = 8
Autovakuum
Med jævne mellemrum, baseret på en masse konfigurationsindstillinger, vil Postgres spwan en masse arbejdere, der vil STØVSUGE databasetabellerne. Dette kaldes selvfølgelig autovakuum, og antallet af arbejdere, som autovakuumstarteren afføder hver gang, kan indstilles via konfigurationsindstillingen:
# the maximum number of autovacuum processes
autovacuum_max_workers = 8
WAL-komprimering
Hvis du har CPU til overs, kan du bytte CPU med diskbåndbredde ved at komprimere siderne, der er skrevet ind i WAL-filerne. Dette reducerer mængden af data, der skal skrives til disken, på bekostning af flere CPU-cyklusser for at komprimere dataene. Det reducerer også størrelsen af data, der skal sendes over ledningen til streaming replikering.
Praktisk talt er fordelene ved WAL-komprimering de meget rimelige omkostninger værd. For at slå det til, brug:
# compresses full page images written to WAL
wal_compression = on
Hukommelse
Hvad skaleres automatisk
OS administrerer og bruger automatisk hukommelse, der ikke bruges af nogen applikation til cachelagring af data læst fra og skrevet til disken for nylig. Dette fremskynder disk-intensive applikationer, og bestemt PostgreSQL.
I Linux, den mest populære vært for Postgres, kan størrelsen på OS-diskcachen ikke indstilles af brugeren. Dets styring er internt i Linux. Under hukommelsestryk vil det give diskcachehukommelse til applikationer.
Hvad skal justeres
Forespørgselsplanlægning
Forespørgselsplanlæggeren skal inkludere mængden af diskcache leveret af OS, som en faktor i dets estimater. Hvis du har formået at øge OS diskcachen betydeligt (ved at øge den tilgængelige hukommelse), kan en forøgelse af denne konfigurationsindstilling hjælpe med at forbedre planlæggerens estimater:
# the planner's assumption about the effective size
# of the disk cache that is available to a single query.
effective_cache_size = 64GB
Delt hukommelse
PostgreSQL bruger et sæt buffere, der deles mellem alle arbejdere og backendprocesser. Disse kaldes delte buffere , og mængden af hukommelse, der er allokeret til delte buffere, indstilles ved hjælp af konfigurationsindstillingen:
shared_buffers = 32GB
Midlertidige buffere
Når midlertidige tabeller tilgås af en forespørgsel, allokeres buffere til cacheindholdet, der læses ind. Størrelsen af denne buffer indstilles ved hjælp af konfigurationsindstillingen:
# the maximum number of temporary buffers used
# by each database session
temp_buffers = 100MB
Hvis du har hukommelse til overs og forespørgsler, der i høj grad bruger midlertidige tabeller, kan en forøgelse af denne værdi fremskynde sådanne forespørgsler.
Arbejdshukommelse
Arbejdshukommelse tildeles lokalt og privat af backends. Det bruges til at udføre sorteringer og sammenføjninger uden at skulle oprette til midlertidige tabeller. Hvis du øger dette fra standarden på 4 MB, kan forespørgsler fuldføres hurtigere ved under midlertidig tabeloprettelse:
# the amount of memory to be used by internal sort
# operations and hash tables before writing to temporary disk files
work_mem = 16MB
Vedligeholdelsesoperationer
Hukommelsen, der bruges af VACUUM, indeksoprettelse og andre sådanne vedligeholdelseskommandoer, styres af konfigurationsindstillingen maintenance_work_mem
. At øge dette beløb kan fremskynde disse operationer, især på indekser eller tabeller, der skal genskabes.
Hukommelsen, der bruges af autovakuumarbejderne, kan tages fra vedligeholdelsesarbejdshukommelsen (ved at indstille autovacuum_work_mem = -1
) eller konfigureret uafhængigt.
# 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
Disk
Hvad skaleres automatisk
Diske kan gøres større, hurtigere eller mere samtidige. Størrelsen på disken er den eneste ting, som PostgreSQL ikke behøver at blive instrueret om. Som standard vil PostgreSQL ikke begrænse sig selv fra at bruge tilgængelig diskplads. Dette er normalt fint.
Du kan dog sætte en grænse for den samlede størrelse af midlertidige filer, der er oprettet, for at give en vis grad af beskyttelse mod forespørgsler, der forsøger at sortere en milliard rækker og lignende:
# the maximum amount of disk space that a process
# can use for temporary files
temp_file_limit = 500GB
Hvad skal justeres
Samtidig
RAID-ed-diske og filsystemer som ZFS kan konfigureres til at understøtte mere samtidighed. Det vil sige, at du kan have nogle få disklæsninger/skrivninger, der betjenes samtidigt af sådanne filsystemer på grund af den måde, hvorpå data lagres eller håndteres internt.
Du kan lade Postgres udstede flere samtidige disk I/O ved at bruge denne konfigurationsindstilling:
# the number of concurrent disk I/O operations that
# PostgreSQL expects can be executed simultaneously
effective_io_concurrency = 4
Dette bruges dog kun i øjeblikket af bitmap-heap-scanninger.
Tilfældige sideomkostninger
Postgres-forespørgselsplanlæggeren antager, at sekventielle læsninger er hurtigere end randomreads. Præcis hvor meget hurtigere er en værdi, du kan justere. Som standard antager den, at tilfældige læsninger er 4 gange dyrere.
Afhængigt af din diskopsætning, arbejdsbelastning og benchmarking, hvis du er sikker på, at tilfældige læsninger kun er dobbelt så dyre som sekventielle læsninger, kan du fortælle det til Postgres:
# 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
For at drage fordel af flere diske, som ikke er monteret som ét stort enkelt filsystem, kan du bruge tablespaces. Med tablespaces kan du placere tabeller eller indeksere forskellige filsystemer. Dette kan forbedre samtidighed og giver en nem måde at håndtere tabelvækst på.
CREATE TABLESPACE disk2 LOCATION '/mnt/disk2/postgres';
Læs mere om tablespaces her.
Netværk
Netværk er normalt den mindst brugte ressource på en PostgreSQL-server og er sjældent mættet. Hvis du har brug for at skalere, er det nemt nok at tilføje flere netværksgrænseflader med hver sin IP og få PostreSQL til at lytte til dem alle:
listen_addresses = '10.1.0.10,10.1.0.11'
Klienterne skal være belastningsbalancerede på tværs af alle de IP'er, Postgreslistens på.
Andet
Der er et par andre konfigurationsindstillinger, der kan justeres, hvoraf de fleste bruger mere CPU og hukommelse.
Partitionsvise handlinger
Postgres 10 introducerede tabelpartitionering, som blev forbedret i Postgres 11. Nogle forespørgselsoptimeringer på partitioner er ikke slået til som standard, da de kan resultere i højere CPU- og hukommelsesforbrug. Disse er:
# 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