PostgreSQL er en af de mest populære open source-databaser i verden og har succesfulde implementeringer på tværs af flere missionskritiske miljøer på tværs af forskellige domæner, ved hjælp af real-time high-end OLTP-applikationer, der udfører millioner og milliarder af transaktioner om dagen. PostgreSQL I/O er ret pålidelig, stabil og ydende på stort set enhver hardware, inklusive endda cloud.
For at sikre, at databaser fungerer i den forventede skala med forventede svartider, er der behov for en vis performance engineering. Nå, opnåelsen af god databaseydelse afhænger af forskellige faktorer. Databaseydelsen kan gå dårligt af forskellige årsager såsom infrastrukturdimensionering, ineffektiv databasevedligeholdelsesstrategi, dårlig SQL-kode eller dårligt konfigurerede databaseprocesser, der ikke udnytter alle de tilgængelige ressourcer - CPU, hukommelse, netværksbåndbredde og disk I/O.
Hvad kan få databaseydeevnen til at forringes?
- Dårligt skrevne forespørgsler med dårlige joinforbindelser, logik osv., der kræver meget CPU og hukommelse
- Forespørgsler, der udfører fuld-tabel-scanninger på store tabeller på grund af forkert indeksering
- Dårlig databasevedligeholdelse uden ordentlig statistik på plads
- Ineffektiv kapacitetsplanlægning resulterer i utilstrækkeligt dimensioneret infrastruktur
- Ukorrekt logisk og fysisk design
- Ingen forbindelsespooling på plads, hvilket får applikationer til at oprette et stort antal forbindelser på en ukontrollerbar måde
Så det er en masse potentielle områder, der kan forårsage præstationsproblemer. Et af de væsentlige områder, jeg gerne vil fokusere på i denne blog, er, hvordan man tuner PostgreSQL I/O (Input / Output) ydeevne. Justering af input/output-operationerne i PostgreSQL er afgørende, især i et højtransaktionsmiljø som OLTP eller i et datavarehusmiljø med kompleks dataanalyse på store datasæt.
De fleste gange skyldes problemer med databasens ydeevne hovedsageligt på grund af høj I/O. Det betyder, at databaseprocesser bruger mere tid på enten at skrive til eller læse fra disken. Enhver realtidsdataoperation er I/O-bundet, det er bydende nødvendigt at sikre, at databasen er I/O-tunet. I denne blog vil jeg fokusere på almindelige I/O-problemer, som PostgreSQL-databaser kan støde på i produktionsmiljøer i realtid.
Justering af PostgreSQL I/O
Tuning af PostgreSQL I/O er bydende nødvendigt for at opbygge en yderst effektiv og skalerbar databasearkitektur. Lad os se på forskellige faktorer, der påvirker I/O-ydelsen:
- Indeksering
- Partitionering
- Kontrolposter
- VAKUUM, ANALYSER (med FILLFACTOR)
- Andre I/O-problemer
- PostgreSQL I/O på Cloud
- Værktøjer
Indeksering
Indeksering er en af de centrale tuning-teknikker, som spiller en afgørende rolle i at forbedre databasens I/O-ydeevne. Dette gælder i virkeligheden enhver database. PostgreSQL understøtter forskellige indekstyper, som i høj grad kan fremskynde læseoperationer, hvilket giver forbedret skalerbarhed for applikationer. Selvom det er ret simpelt og ligetil at oprette indekser, er det vigtigt for DBA'er og udviklere at have viden om, hvilken type indeks de skal vælge, og på hvilke kolonner. Sidstnævnte er baseret på forskellige faktorer som forespørgselskompleksitet, datatype, datakardinalitet, mængden af skrivninger, datastørrelse, diskarkitektur, infrastruktur (offentlig sky, privat sky eller lokalt) osv.
Mens indeksering dramatisk kan forbedre forespørgselslæseydelsen, kan det også bremse skrivningen, der rammer de indekserede kolonner. Lad os se på et eksempel:
Indeksers indvirkning på READ-operationer
En tabel kaldet emp med omkring 1 million rækker.
LÆS Ydeevne uden et indeks
postgres=# select * from emp where eid=10;
eid | ename | peid | did | doj
-----+---------------+--------+------+------------
10 | emp | | 1 | 2018-06-06
(1 row)
Time: 70.020 ms => took about 70+ milli-seconds to respond with on row
LÆS Ydeevne med et indeks
Lad os sætte et indeks på eid kolonne og se forskellen
postgres=# create index indx001 on emp ( eid );
CREATE INDEX
postgres=# select * from emp where eid=10;
eid | ename | peid | did | doj
------+-------------+-------+------+------------
10 | emp | | 1 | 2018-06-06
(1 row)
Time: 0.454 ms => 0.4+ milli-seconds!!! thats a huge difference - isn’t it?
Så indeksering er vigtig.
Indeksers indvirkning på WRITE-operationer
Indekser sænker ydeevnen af skrivninger. Selvom indekserne har en indvirkning på alle typer skriveoperationer, lad os se på nogle analyser af indvirkningen af indekser på INSERT'er
Indsættelse af 1 million rækker i en tabel uden indekser
postgres=# do $$
postgres$# declare
postgres$# i integer;
postgres$# begin
postgres$# for i in 1..1000000 loop
postgres$# insert into emp values (i,'emp',null,1,current_date);
postgres$# end loop;
postgres$# end $$;
DO
Time: 4818.470 ms (00:04.818) => Takes about 4.8 seconds
Indsættelse af de samme 1 million rækker med et indeks
Lad os først oprette et indeks
postgres=# create index indx001 on emp ( eid );
CREATE INDEX
postgres=# do $$
postgres$# declare
postgres$# i integer;
postgres$# begin
postgres$# for i in 1..1000000 loop
postgres$# insert into emp values (i,'emp',null,1,current_date);
postgres$# end loop;
postgres$# end $$;
DO
Time: 7825.494 ms (00:07.825) => Takes about 7.8 seconds
Så, som vi kan observere, steg INSERT-tiden med 80% med kun ét indeks og kan tage meget længere tid at afslutte, når der er flere indekser. Det kan blive endnu værre, når der er funktionsbaserede indekser. Det må DBA'er leve med! Indekser vil øge skriveydelsen. Der er dog måder at tackle dette problem på, som er afhængig af diskarkitekturen. Hvis databaseserveren bruger flere diskfilsystemer, kan indekserne og tabellerne placeres på tværs af flere tablespaces på tværs af flere diskfilsystemer. På denne måde kan der opnås bedre I/O-ydelse.
Tips til indeksstyring
- Forstå behovet for indekser. Intelligent indeksering er nøglen.
- Undgå at oprette flere indekser, og absolut ingen unødvendige indekser, dette kan virkelig forringe skriveydeevnen.
- Overvåg brugen af indekser, og slip eventuelle ubrugte indekser.
- Når indekserede kolonner udsættes for dataændringer, bliver indekser også oppustede. Så reorganiser jævnligt indekser.
Partitionering
En effektiv opdelingsstrategi kan reducere I/O-ydelsesproblemer i høj grad. Store tabeller kan opdeles baseret på forretningslogik. PostgreSQL understøtter tabelopdeling. Selvom det ikke fuldt ud understøtter alle funktionerne i øjeblikket, kan det kun hjælpe med nogle af real-time use-cases. I PostgreSQL er opdelte underordnede tabeller fuldstændig individuelle for mastertabellen, som er en flaskehals. F.eks. kan begrænsninger, der er oprettet på mastertabellen, ikke automatisk nedarves til de underordnede tabeller.
Men fra balancerende I/O-perspektiv kan partitionering virkelig hjælpe. Alle underordnede partitioner kan opdeles på tværs af flere tablespaces og diskfilsystemer. Forespørgsler med et datointerval i "where"-klausulen, der rammer tabellen, opdelt baseret på datointerval, kan drage fordel af partitionering ved blot at scanne en eller to partitioner i stedet for hele tabellen.
Kontrolpost
Kontrolpunkter definerer databasens konsistente tilstand. De er kritiske, og det er vigtigt, at kontrolpunkter forekommer regelmæssigt nok til at sikre, at dataændringer gemmes permanent på disken, og at databasen hele tiden er i konsistent tilstand. Når det er sagt, kan forkert konfiguration af kontrolpunkter føre til I/O-ydeevneproblemer. DBA'er skal være omhyggelige med at konfigurere kontrolpunkter for at sikre, at der ikke er nogen I/O-spids, og dette afhænger også af, hvor gode diskene er, og hvor godt datafillayoutet er opbygget.
Hvilket kontrolpunkt gør ?
Enkelt sagt vil checkpoints sikre:
- Alle de forpligtede data skrives til datafilerne på disken.
- Clog-filer opdateres med commit-status.
- Transaktionslogfiler i mappen pg_xlog (nu pg_wal) genbruges.
Det forklarer, hvor I/O-intensive kontrolpunkter er. Der er parametre i postgresql.conf, som kan konfigureres/tunes til at kontrollere kontrolpunkters adfærd, og disse parametre er max_wal_size, min_wal_size, checkpoint_timeout og checkpoint_completion_target. Disse parametre bestemmer, hvor ofte kontrolpunkterne skal forekomme, og inden for hvor lang tid kontrolpunkterne skal afsluttes.
Hvordan forstår man, hvilken konfiguration der er bedre til kontrolpunkter? Hvordan tuner man dem?
Her er nogle tips:
- Evaluer databasen TPS. Evaluer den samlede mængde transaktioner, der finder sted i databasen på en hverdag, og identificer også på hvilket tidspunkt det højeste antal transaktioner rammer databasen.
- Diskuter med applikationsudviklere og andre tekniske teams regelmæssigt for at forstå databasens transaktionshastighedsstatistikker samt fremtidig transaktionsvækst.
- Dette kan også gøres fra databasen:
-
Overvåg databasen og evaluer antallet af transaktioner, der finder sted i løbet af dagen. Dette kan gøres ved at forespørge pgcatalog-tabeller som pg_stat_user_tables.
-
Evaluer antallet af wal-arkivfiler, der genereres pr. dag
-
Overvåg for at forstå, hvordan kontrolpunkterne klarer sig ved at aktivere parameteren log_checkpoints
2018-06-06 15:03:16.446 IST [2111] LOG: checkpoint starting: xlog 2018-06-06 15:03:22.734 IST [2111] LOG: checkpoint complete: wrote 12112 buffers (73.9%); 0 WAL file(s) added, 0 removed, 25 recycled; write=6.058 s, sync=0.218 s, total=6.287 s; sync files=4, longest=0.178 s, average=0.054 s; distance=409706 kB, estimate=412479 kB
-
Forstå, om den aktuelle kontrolpunktkonfiguration er god nok til databasen. Konfigurer checkpoint_warning-parameteren (som standard konfigureret til 30 sekunder) for at se nedenstående advarsler i postgres-logfilerne.
2018-06-06 15:02:42.295 IST [2111] LOG: checkpoints are occurring too frequently (11 seconds apart) 2018-06-06 15:02:42.295 IST [2111] HINT: Consider increasing the configuration parameter "max_wal_size".
-
Hvad betyder ovenstående advarsel?
Kontrolpunkter forekommer generelt, når max_wal_size (1 GB som standard, hvilket betyder 64 WAL-filer) af logfiler er fyldt op, eller når checkpoint_timeout (hvert 5. minut hver standard) nås. Ovenstående advarsel betyder, at konfigureret max_wal_size ikke er tilstrækkelig, og kontrolpunkterne forekommer hvert 11. sekund, hvilket igen betyder, at 64 WAL-filer i PG_WAL-biblioteket bliver fyldt op på kun 11 sekunder, hvilket er for hyppigt. Med andre ord, hvis der er mindre hyppige transaktioner, så vil kontrolpunkterne forekomme hvert 5. minut. Så, som tippet antyder, skal du øge max_wal_size-parameteren til en højere værdi, max_min_size-parameteren kan øges til den samme eller en mindre end tidligere.
En anden kritisk parameter at overveje fra I/O-ydelsesperspektiv er checkpoint_completion_target, som som standard er konfigureret til 0,5.
checkpoint_completion_target =0,5 x checkpoint_timeout =2,5 minutter
Det betyder, at checkpoints har 2,5 minutter til at synkronisere de beskidte blokke til disken. Er 2,5 minutter nok? Det skal evalueres. Hvis antallet af beskidte blokke, der skal skrives, er meget højt, så kan 2,5 minutter virke meget meget aggressive, og det er, når der kan observeres en I/O-spids. Konfiguration af completion_target parameteren skal udføres baseret på max_wal_size og checkpoint_timeout værdier. Hvis disse parametre hæves til en højere værdi, kan du overveje at hæve checkpoint_completion_target tilsvarende.
VAKUUM, ANALYSER (med FILLFACTOR)
VACUUM er en af de mest kraftfulde funktioner i PostgreSQL. Den kan bruges til at fjerne bloats (fragmenteret plads) i tabeller og indekser og genereres af transaktioner. Databasen skal udsættes for STØVSUGNING regelmæssigt for at sikre sund vedligeholdelse og bedre ydeevne. Igen, ikke at støvsuge databasen regelmæssigt kan føre til alvorlige ydeevneproblemer. ANALYSE skal udføres sammen med VACUUM (VACUUM ANALYZE) for at sikre opdaterede statistikker for forespørgselsplanlæggeren.
VAKUUMANALYSE kan udføres på to måder:manuel, automatisk eller begge dele. I et realtidsproduktionsmiljø er det generelt begge dele. Automatisk VACUUM aktiveres af parameteren "autovacuum", som som standard er konfigureret til "on". Med autovakuum aktiveret begynder PostgreSQL automatisk at støvsuge tabellerne med jævne mellemrum. De kandidattabeller, der har behov for støvsugning, opfanges af autovakuumprocesser baseret på forskellige tærskler, der er sat af forskellige autovakuum*-parametre, disse parametre kan justeres/tunes for at sikre, at oppustninger af tabellerne ryddes med jævne mellemrum. Lad os se på nogle parametre og deres anvendelse -
Autovakuumparametre
autovacuum=on | Denne parameter bruges til at aktivere/deaktivere autovakuum. Standard er "on". |
log_autovacuum_min_duration =-1 | Logger varigheden af autovakuumprocessen. Dette er vigtigt for at forstå, hvor længe autovakuumprocessen kørte. |
autovacuum_max_workers =3 | Antal autovakuumprocesser påkrævet. Dette afhænger af, hvor aggressive databasetransaktioner er, og hvor mange CPU'er du kan tilbyde til autovakuumprocesser. |
autovacuum_naptime =1 min. | Hviletid for autovakuum mellem autovakuumkørsler. |
Parametre, der definerer tærsklen for, at autovakuum-processen starter
Autovakuumopgave(r) starter, når en vis tærskel er nået. Nedenfor er de parametre, som kan bruges til at indstille en bestemt tærskel, baseret på hvilken autovakuumprocessen starter.
autovacuum_vacuum_threshold =50 | Tabellen vil blive støvsuget, når minimum 50 rækker vil blive opdateret/slettet i en tabel. |
autovacuum_analyze_threshold =50 | Tabellen vil blive analyseret, når minimum 50 rækker vil blive opdateret/slettet i en tabel. |
autovacuum_vacuum_scale_factor =0,2 | Tabellen vil blive støvsuget, når minimum 20 % af rækkerne er opdateret/slettet i en tabel. |
autovacuum_analyze_scale_factor =0,1 | Tabellen vil blive støvsuget, når minimum 10 % af rækkerne er opdateret/slettet i en tabel. |
Parametre over tærskelværdien kan ændres baseret på databaseadfærd. DBA'er skal analysere og identificere de varme borde og sikre, at disse tabeller støvsuges så ofte som muligt for at sikre god ydeevne. At nå frem til en vis værdi for disse parametre kan være en udfordring i et miljø med høje transaktioner, hvor dataændringer sker hvert sekund. Mange gange bemærkede jeg, at autovakuumprocesser tager ret lang tid at fuldføre og ender med at forbruge for mange ressourcer i produktionssystemer.
Jeg vil foreslå, at du ikke er helt afhængig af autovakuumprocessen, den bedste måde er at planlægge et natligt VACUUM ANALYSE-job, så byrden på autovakuum reduceres. Til at starte med kan du overveje manuelt at STØVSUGE store borde med en høj transaktionshastighed.
VAKUUM FULD
VACUUM FULL hjælper med at genvinde den oppustede plads i tabellerne og indekserne. Dette værktøj kan ikke bruges, når databasen er online, da det låser bordet. Tabeller må kun udsættes for VACUUM FULL, når applikationerne lukkes ned. Indekser vil også blive reorganiseret sammen med tabeller under VACUUM FULL.
Lad os tage et kig på virkningen af VACUUM ANALYZE
Opblødning:Hvordan identificerer man oppustethed? Hvornår genereres oppustethed?
Her er nogle tests:
Jeg har fået en tabel på størrelse 1 GB med 10 millioner rækker.
postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
----------------
1
postgres=# select count(*) From pgbench_accounts ;
count
-----------------
10000000
Lad os se på virkningen af oppustethed på en simpel forespørgsel:vælg * fra pgbench_accounts;
Nedenfor er den forklarende plan for forespørgslen:
postgres=# explain analyze select * from pgbench_accounts;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on pgbench_accounts (cost=0.00..263935.00 rows=10000000 width=97)
(actual time=0.033..1054.257 rows=10000000 loops=1)
Planning time: 0.255 ms
Execution time: 1494.448 ms
Lad os nu opdatere alle rækkerne i tabellen og se virkningen af ovenstående SELECT-forespørgsel.
postgres=# update pgbench_accounts set abalance=1;
UPDATE 10000000
postgres=# select count(*) From pgbench_accounts ;
count
-----------------
10000000
Nedenfor er EXPLAIN PLAN for forespørgslen efter UPDATE-udførelsen.
postgres=# explain analyze select * from pgbench_accounts;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on pgbench_accounts (cost=0.00..527868.39 rows=19999939 width=97)
(actual time=404.474..1520.175 rows=10000000 loops=1)
Planning time: 0.051 ms
Execution time: 1958.532 ms
Tabellens størrelse steg til 2 GB efter OPDATERING
postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
-----------------
2
Hvis du kan observere og sammenligne omkostningstallene for den tidligere FORKLARPLAN, er der en enorm forskel. Omkostningerne er steget med en stor margin. Endnu vigtigere, hvis du observerer omhyggeligt, er antallet af rækker (lidt over 19 millioner), der scannes efter OPDATERING, højere, hvilket er næsten to gange de faktiske eksisterende rækker (10 millioner). Det betyder, at antallet af oppustede rækker er 9+ millioner, og at den faktiske tid også er steget, og at eksekveringstiden er steget fra 1,4 sekunder til 1,9 sekunder.
Så det er virkningen af ikke at STØVSUGE TABELLEN efter OPDATERING. Ovenstående EXPLAIN PLAN-tal betyder præcist, at tabellen er oppustet.
Hvordan identificerer man, om bordet er oppustet? Brug pgstattuple bidragsmodul:
postgres=# select * from pgstattuple('pgbench_accounts');
table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent
------------+-------------+------------+---------------+------------------+----------------+--------------------+------------+--------------
2685902848 | 10000000 | 1210000000 | 45.05 | 9879891 | 1195466811 | 44.51 | 52096468 | 1.94
Ovenstående tal angiver, at halvdelen af bordet er oppustet.
Lad os VAKUUMANALYSER bordet og se virkningen nu:
postgres=# VACUUM ANALYZE pgbench_accounts ;
VACUUM
postgres=# explain analyze select * from pgbench_accounts;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------
Seq Scan on pgbench_accounts (cost=0.00..428189.05 rows=10032005 width=97)
(actual time=400.023..1472.118 rows=10000000 loops=1)
Planning time: 4.374 ms
Execution time: 1913.541 ms
Efter VACUUM ANALYSE er omkostningstallene faldet. Nu viser antallet af scannede rækker tæt på 10 millioner, også den faktiske tid og eksekveringstiden ændrede sig ikke meget. Det skyldes, at selvom svulsten i bordet er forsvundet, forbliver størrelsen af bordet, der skal scannes, den samme. Nedenfor er det pgstattuple output efter VACUUM ANALYSE.
postgres=# select * from pgstattuple('pgbench_accounts');
table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent
------------+-------------+------------+---------------+------------------+----------------+--------------------+------------+--------------
2685902848 | 10000000 | 1210000000 | 45.05 | 0 | 0 | 0 | 1316722516 | 49.02
Ovenstående tal angiver, at alle oppustetheder (døde tupler) er forsvundet.
Lad os se på virkningen af VACUUM FULL ANALYSE og se, hvad der sker:
postgres=# vacuum full analyze pgbench_accounts ;
VACUUM
postgres=# explain analyze select * from pgbench_accounts;
QUERY PLAN
---------------------------------------------------------------------------
Seq Scan on pgbench_accounts (cost=0.00..263935.35 rows=10000035 width=97)
(actual time=0.015..1089.726 rows=10000000 loops=1)
Planning time: 0.148 ms
Execution time: 1532.596 ms
Hvis du observerer, svarer det faktiske tidspunkt og udførelsestidstallet til tallene før OPDATERING. Desuden er bordets størrelse nu faldet fra 2 GB til 1 GB.
postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
-----------------
1
Det er virkningen af VACUUM FULL.
FYLDNINGSFAKTOR
FILLFACTOR er en meget vigtig egenskab, som kan gøre en reel forskel for databasevedligeholdelsesstrategien på tabel- og indeksniveau. Denne værdi angiver mængden af plads, der skal bruges af INSERT'erne i en datablok. FILLFACTOR-værdien er som standard 100 %, hvilket betyder, at INSERT'er kan udnytte al den tilgængelige plads i en datablok. Det betyder også, at der ikke er plads til OPDATERINGER. Denne værdi kan sænkes til en bestemt værdi for stærkt opdaterede tabeller.
Denne parameter kan konfigureres til hver tabel og et indeks. Hvis FILLFACTOR er konfigureret til den optimale værdi, kan du også se en reel forskel i VACUUM-ydeevne og forespørgselsydeevne. Kort sagt sikrer optimale FILLFACTOR-værdier, at unødvendigt antal blokke ikke allokeres.
Lad os se på det samme eksempel ovenfor -
Tabellen har en million rækker
postgres=# select count(*) From pgbench_accounts ;
count
-----------------
10000000
Før opdatering er bordets størrelse 1 GB
postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
--------
1
postgres=# update pgbench_accounts set abalance=1;
UPDATE 10000000
Efter opdateringen steg tabellens størrelse til 2 GB efter OPDATERING
postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
---------
2
Det betyder, at antallet af blokke tildelt bordet er steget med 100%. Hvis FILLFACTOR blev konfigureret, er størrelsen af tabellen muligvis ikke steget med denne margen.
Hvordan ved man, hvilken værdi der skal konfigureres til FILLFACTOR?
Det hele afhænger af hvilke kolonner der opdateres og størrelsen på de opdaterede kolonner. Generelt ville det være godt at evaluere FILLFACTOR-værdien ved at teste den i UAT-databaser. Hvis kolonnerne, der opdateres, f.eks. er 10 % af hele tabellen, så overvej at konfigurere fillfactor til 90 % eller 80 %.
Vigtig bemærkning:
Hvis du ændrer FILLFACTOR-værdien for den eksisterende tabel med dataene, skal du lave en VACUUM FULL eller en omorganisering af tabellen for at sikre, at FILLFACTOR-værdien er aktiv for de eksisterende data.
STØVSUGSTIPS
- Som nævnt ovenfor, overvej at køre VACUUM ANALYZE-jobbet manuelt hver nat på de meget brugte borde, selv når autovakuum er aktiveret.
- Overvej at køre VACUUM ANALYZE på tabeller efter bulk INSERT. Dette er vigtigt, da mange mener, at STØVSUGNING muligvis ikke er nødvendig efter INDSÆTNINGER.
- Overvåg for at sikre, at meget aktive tabeller støvsuges regelmæssigt ved at forespørge tabellen pg_stat_user_tables.
- Brug pg_stattuple bidragsmodul til at identificere størrelsen af det oppustede rum i tabelsegmenterne.
- VACUUM FULL-værktøjet kan ikke bruges på produktionsdatabasesystemer. Overvej at bruge værktøjer som pg_reorg eller pg_repack, som hjælper med at omorganisere tabeller og indekser online uden låse.
- Sørg for, at AUTOVACUUM-processen kører i længere tid i arbejdstiden (høj trafik).
- Aktiver log_autovacuum_min_duration parameter for at logge timing og varighed af AUTOVACUUM processer.
- Vigtigt, sørg for, at FILLFACTOR er konfigureret til en optimal værdi på høje transaktionstabeller og indekser.
Andre I/O-problemer
Disksortering
Forespørgsler, der udfører sortering, er en anden almindelig hændelse i realtidsproduktionsdatabaser, og de fleste af disse kan ikke undgås. Forespørgsler ved hjælp af klausuler som GROUP BY, ORDER BY, DISTINCT, CREATE INDEX, VACUUM FULL etc. udfører sortering og sorteringen kan foregå på disk. Sortering foregår i hukommelsen, hvis udvælgelsen og sorteringen sker ud fra indekserede kolonner. Det er her sammensatte indekser spiller en nøglerolle. Indekser cachelagres aggressivt i hukommelsen. Ellers, hvis der opstår et behov for at sortere dataene på disken, vil ydeevnen blive drastisk langsommere.
For at sikre, at sortering finder sted i hukommelsen, kan parameteren work_mem bruges. Denne parameter kan konfigureres til en værdi, således at hele sorteringen kan udføres i hukommelsen. Kernefordelen ved denne parameter er, at den, udover at konfigurere den i postgresql.conf, også kan konfigureres på sessionsniveau, brugerniveau eller databaseniveau. Hvor meget skal værdien work_mem være? Hvordan ved man, hvilke forespørgsler der udfører disksortering? Hvordan overvåger man forespørgsler, der udfører disksortering på en produktionsdatabase i realtid?
Svaret er - konfigurer log_temp_files parameter til en bestemt værdi. Værdien er i bytes, en værdi på 0 logger alle de midlertidige filer (sammen med deres størrelser) genereret på disken på grund af disksortering. Når parameteren er konfigureret, vil du kunne se følgende meddelelser i logfilerne
2018-06-07 22:48:02.358 IST [4219] LOG: temporary file: path "base/pgsql_tmp/pgsql_tmp4219.0", size 200425472
2018-06-07 22:48:02.358 IST [4219] STATEMENT: create index bid_idx on pgbench_accounts(bid);
2018-06-07 22:48:02.366 IST [4219] LOG: duration: 6421.705 ms statement: create index bid_idx on pgbench_accounts(bid);
Ovenstående meddelelse betyder, at CREATE INDEX-forespørgslen udførte disksortering og har genereret en fil med størrelsen 200425472 bytes, som er 191+ MB. Det betyder præcist, at work_mem-parameteren skal konfigureres til 191+ MB eller derover, for at denne specifikke forespørgsel kan udføre hukommelsessortering.
Nå, for applikationsforespørgslerne kan work_mem-parameteren kun konfigureres på brugerniveau. Før du gør det, skal du være opmærksom på antallet af forbindelser, som brugeren laver til databasen, og antallet af sorteringsforespørgsler, der udføres af den pågældende bruger. Fordi PostgreSQL forsøger at allokere work_mem til hver proces (udfører sortering) i hver forbindelse, hvilket potentielt kunne udsulte hukommelsen på databaseserveren.
Layout af databasefilsystem
At designe et effektivt og præstationsfremmende databasefilsystemlayout er vigtigt ud fra ydeevne- og skalerbarhedsperspektiv. Det er vigtigt, at dette ikke afhænger af databasestørrelsen. Generelt er opfattelsen, at store databaser vil have brug for højtydende diskarkitektur, hvilket IKKE er sandt. Selvom databasestørrelsen er 50 GB, har du muligvis brug for en god diskarkitektur. Og det er måske ikke muligt uden at medføre ekstra omkostninger.
Her er nogle TIPS til det samme:
- Sørg for, at databasen har flere tablespaces med tabeller og indekser grupperet baseret på transaktionsraterne.
- Tablespacet skal placeres på tværs af flere diskfilsystemer for at få balanceret I/O. Dette vil også sikre, at flere CPU'er kommer i spil for at udføre transaktioner på tværs af flere diske.
- Overvej at placere biblioteket pg_xlog eller pg_wal på en separat disk i en database med høje transaktioner.
- Sørg for, at *_cost-parametre er konfigureret baseret på infrastrukturen
- Brug iostat, mpstat og andre I/O-overvågningsværktøjer til at forstå I/O-statistikkerne på tværs af alle diske og arkitekt/administrer databaseobjekterne i overensstemmelse hermed.
PostgreSQL på Cloud
Infrastruktur er afgørende for god databaseydelse. Performance engineering strategier er forskellige baseret på infrastruktur og miljø. Der skal tages særlig hensyn til PostgreSQL-databaser, der hostes i skyen. Ydeevnebenchmarking for databaser hostet på fysiske barebone-servere i et lokalt datacenter kan være helt anderledes end databaser hostet i den offentlige sky.
Generelt kan cloud-forekomster være lidt langsommere, og benchmarks adskiller sig med betydelig margin, især med hensyn til I/O. Udfør altid I/O-latenstjek, før du vælger / bygger en cloud-instans. Til min overraskelse lærte jeg, at ydeevnen af cloud-instanser også kan variere afhængigt af regionerne, selvom de er fra den samme cloud-udbyder. For at forklare dette yderligere kan en cloud-instans med samme specifikationer bygget i to forskellige regioner give dig forskellige resultater.
Masseindlæsning af data
Offline bulk dataindlæsningsoperationer er ret almindelige i databaseverdenen. De kan generere betydelig I/O-belastning, hvilket igen sænker dataindlæsningsydelsen. Jeg har stået over for sådanne udfordringer i min erfaring som DBA. Ofte bliver dataindlæsningen frygtelig langsom og skal tunes. Her er nogle tips. Husk, disse gælder kun for offline-dataindlæsningsoperationer og kan ikke tages i betragtning til dataindlæsning i en live-produktionsdatabase.
- Da de fleste dataindlæsningsoperationer udføres uden for arbejdstiden, skal du sikre dig, at følgende parametre er konfigureret under dataindlæsningen -
- Konfigurer checkpoint-relaterede værdier store nok, så checkpoints ikke forårsager problemer med ydeevnen.
- Sluk for full_page_write
- Slå arkivering fra wal fra
- Konfigurer parameteren synchronous_commit til "fra"
- Slip begrænsninger og indekser for de tabeller, der er udsat for dataindlæsningen (begrænsninger og indekser kan genskabes efter dataindlæsningen med en større work_mem-værdi)
- Hvis du foretager dataindlæsningen fra en CSV-fil, kan større maintenance_work_mem give dig gode resultater.
- Selvom der vil være en betydelig ydeevnefordel, Sluk IKKE fsync-parameteren, da det kan føre til datakorruption.
TIPS til cloud-ydeevneanalyse
- Udfør grundige I/O-latenstest ved hjælp af pgbench. Efter min erfaring havde jeg temmelig almindelige resultater, da jeg udførte disklatenstjek som en del af TPS-evaluering. Der var problemer med cache-ydeevne på nogle offentlige cloud-forekomster. Dette vil hjælpe med at vælge de passende specifikationer for den cloud-instans, der er valgt til databaserne.
- Skyforekomster kan fungere forskelligt fra område til område. En cloud-instans med bestemte specifikationer i en region kan give forskellige ydeevneresultater sammenlignet med en cloud-instans med samme specifikationer i en anden region. Mine pgbench-tests udført på flere cloud-forekomster (alle samme specifikationer med den samme cloud-leverandør) på tværs af forskellige regioner gav mig forskellige resultater på nogle af dem. Dette er vigtigt, især når du migrerer til skyen.
- Forespørgselsydeevne i skyen kræver muligvis en anden tuning-tilgang. DBA'er skal bruge *_cost-parametre for at sikre, at der genereres sunde forespørgselsudførelsesplaner.
Værktøjer til at overvåge PostgreSQL-ydelse
There are various tools to monitor PostgreSQL performance. Let me highlight some of those.
- pg_top is a GREAT tool to monitor PostgreSQL database dynamically. I would highly recommend this tool for DBAs for various reasons. This tool has numerous advantages, let me list them out:
- pg_top tool uses textual interface and is similar to Unix “top” utility.
- Will clearly list out the processes and the hardware resources utilized. What excites me with this tool is that it will clearly tell you if a particular process is currently on DISK or CPU - in my view that’s excellent. DBAs can clearly pick the process running for longer time on the disk.
- You can check the EXPLAIN PLAN of the top SQLs dynamically or instantly
- You can also find out what Tables or Indexes are being scanned instantly
- Nagios is a popular monitoring tool for PostgreSQL which has both open-source and commercial versions. Open source version should suffice for monitoring. Custom Perl scripts can be built and plugged into Nagios module.
- Pgbadger is a popular tool which can be used to analyze PostgreSQL log files and generate performance reports. This report can be used to analyze the performance of checkpoints, disk sorting.
- Zabbix is another popular tool used for PostgreSQL monitoring.
ClusterControl is an up-and-coming management platform for PostgreSQL. Apart from monitoring, it also has functionality to deploy replication setups with load balancers, automatic failover, backup management, among others.