sql >> Databasteknik >  >> RDS >> PostgreSQL

Tuning Input/Output (I/O) operationer för PostgreSQL

PostgreSQL är en av de mest populära databaserna med öppen källkod i världen och har framgångsrika implementeringar i flera verksamhetskritiska miljöer över olika domäner, med hjälp av avancerade OLTP-applikationer i realtid som utför miljontals och miljarder transaktioner per dag. PostgreSQL I/O är ganska pålitlig, stabil och presterande på i stort sett vilken hårdvara som helst, inklusive moln.

För att säkerställa att databaser presterar i förväntad skala med förväntade svarstider, finns det ett behov av viss prestandateknik. Nåväl, hur bra databasprestanda uppnås beror på olika faktorer. Databasprestanda kan bli dålig av olika anledningar som infrastrukturdimensionering, ineffektiv databasunderhållsstrategi, dålig SQL-kod eller dåligt konfigurerade databasprocesser som misslyckas med att utnyttja alla tillgängliga resurser - CPU, minne, nätverksbandbredd och disk I/O.

Vad kan orsaka att databasprestanda försämras?

  • Dåligt skrivna frågor med dåliga kopplingar, logik etc. som tar mycket CPU och minne
  • Frågor som utför genomsökningar av hela tabeller på stora tabeller på grund av felaktig indexering
  • Dåligt databasunderhåll utan korrekt statistik på plats
  • Ineffektiv kapacitetsplanering som resulterar i otillräckligt dimensionerad infrastruktur
  • Felaktig logisk och fysisk design
  • Ingen anslutningspoolning på plats, vilket gör att applikationer gör ett stort antal anslutningar på ett okontrollerbart sätt

Så det är många potentiella områden som kan orsaka prestationsproblem. Ett av de viktiga områdena jag skulle vilja fokusera på i den här bloggen är hur man ställer in PostgreSQL I/O (Input/Output) prestanda. Justering av Input/Output-operationerna för PostgreSQL är viktigt, särskilt i en miljö med hög transaktionskapacitet som OLTP eller i en datalagringsmiljö med komplex dataanalys av stora datamängder.

Oftast orsakas problem med databasprestanda främst på grund av hög I/O. Detta innebär att databasprocesser lägger ner mer tid på att antingen skriva till eller läsa från disken. Alla realtidsdataoperationer är I/O-bundna, det är absolut nödvändigt att se till att databasen är I/O-inställd. I den här bloggen kommer jag att fokusera på vanliga I/O-problem som PostgreSQL-databaser kan stöta på i realtidsproduktionsmiljöer.

Justera PostgreSQL I/O

Att trimma PostgreSQL I/O är absolut nödvändigt för att bygga en högpresterande och skalbar databasarkitektur. Låt oss titta på olika faktorer som påverkar I/O-prestanda:

  • Indexering
  • Partitionering
  • Kontrollpunkter
  • VAKUUM, ANALYSE (med FILLFACTOR)
  • Andra I/O-problem
  • PostgreSQL I/O på molnet
  • Verktyg

Indexering

Indexering är en av de centrala inställningsteknikerna som spelar en avgörande roll för att förbättra databas I/O-prestanda. Detta gäller verkligen vilken databas som helst. PostgreSQL stöder olika indextyper som kan påskynda läsoperationer i stor utsträckning, vilket ger förbättrad skalbarhet för applikationer. Även om det är ganska enkelt och okomplicerat att skapa index, är det viktigt för DBA:er och utvecklare att ha kunskap om vilken typ av index de ska välja och på vilka kolumner. Det senare är baserat på olika faktorer som frågekomplexitet, datatyp, datakardinalitet, skrivvolym, datastorlek, diskarkitektur, infrastruktur (offentligt moln, privat moln eller lokalt), etc.

Även om indexering dramatiskt kan förbättra läsprestandan för frågor, kan det också sakta ner skrivningarna som träffar de indexerade kolumnerna. Låt oss titta på ett exempel:

Inverkan av index på LÄS-operationer

En tabell som heter emp med cirka 1 miljon rader.

LÄS Prestanda utan index

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 Prestanda med ett index

Låt oss lägga ett index på eid-kolumnen och se skillnaden

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å indexering är viktigt.

Inverkan av index på WRITE-operationer

Index bromsar prestandan för skrivningar. Även om indexen har en inverkan på alla typer av skrivoperationer, låt oss titta på en analys av inverkan av index på INSERT

Infoga 1 miljon rader i en tabell utan 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: 4818.470 ms (00:04.818) => Takes about 4.8 seconds

Infoga samma 1 miljon rader med ett index

Låt oss skapa ett index först

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 observera, ökade INSERT-tiden med 80 % med bara ett index och kan ta mycket längre tid att slutföra när det finns flera index. Det kan bli ännu värre när det finns funktionsbaserade index. Det är vad DBA:er måste leva med! Index kommer att öka skrivprestandan. Det finns dock sätt att ta itu med det här problemet, som är beroende av diskarkitekturen. Om databasservern använder flera diskfilsystem, kan indexen och tabellerna placeras över flera tabellutrymmen som sitter över flera diskfilsystem. På så sätt kan bättre I/O-prestanda uppnås.

Tips för indexhantering

  • Förstå behovet av index. Intelligent indexering är nyckeln.
  • Undvik att skapa flera index, och definitivt inga onödiga index, detta kan verkligen försämra skrivprestandan.
  • Övervaka användningen av index och släpp eventuella oanvända index.
  • När indexerade kolumner utsätts för dataändringar, blir indexen också svullna. Så, omorganisera indexen regelbundet.

Partitionering

En effektiv partitioneringsstrategi kan reducera I/O-prestandaproblem i stor utsträckning. Stora tabeller kan partitioneras baserat på affärslogik. PostgreSQL stöder tabellpartitionering. Även om det inte fullt ut stöder alla funktioner för tillfället, kan det bara hjälpa till med några av realtidsanvändningsfallen. I PostgreSQL är partitionerade underordnade tabeller helt individuella för mastertabellen som är en flaskhals. T.ex. begränsningar som skapats på huvudtabellen kan inte automatiskt ärvas till de underordnade tabellerna.

Men ur balanserande I/O-perspektiv kan partitionering verkligen hjälpa. Alla underordnade partitioner kan delas över flera tabellutrymmen och diskfilsystem. Frågor med ett datumintervall i "where"-satsen som träffar tabellen, partitionerade baserat på datumintervall, kan dra nytta av partitionering genom att bara skanna en eller två partitioner istället för hela tabellen.

Checkpointing

Kontrollpunkter definierar databasens konsekventa tillstånd. De är kritiska och det är viktigt att kontrollpunkter inträffar tillräckligt regelbundet för att säkerställa att dataändringar sparas permanent på disken och att databasen är i konsekvent tillstånd hela tiden. Som sagt, felaktig konfiguration av kontrollpunkter kan leda till I/O-prestandaproblem. DBA:er måste vara noggranna med att konfigurera kontrollpunkter för att säkerställa att det inte finns någon I/O-spik, och detta beror också på hur bra diskarna är och hur väl layouten för datafilerna är utformad.

Vilken kontrollpunkt gör ?

Enkelt uttryckt kommer checkpoints att säkerställa:

  • Alla registrerade data skrivs till datafilerna på disken.
  • täppa filer uppdateras med commit-status.
  • Transaktionsloggfiler i katalogen pg_xlog (nu pg_wal) återvinns.

Det förklarar hur I/O-intensiva kontrollpunkter är. Det finns parametrar i postgresql.conf som kan konfigureras/justeras för att kontrollera kontrollpunktens beteende och dessa parametrar är max_wal_size, min_wal_size, checkpoint_timeout och checkpoint_completion_target. Dessa parametrar kommer att avgöra hur ofta kontrollpunkterna ska inträffa och inom hur lång tid kontrollpunkterna måste avslutas.

Hur förstår man vilken konfiguration som är bättre för kontrollpunkter? Hur ställer man in dem?

Här är några tips:

  • Utvärdera databasen TPS. Utvärdera den totala volymen transaktioner som sker i databasen under en arbetsdag och identifiera även vid vilken tidpunkt det högsta antalet transaktioner träffar databasen.
  • Diskutera med applikationsutvecklare och andra tekniska team regelbundet för att förstå statistiken över databasens transaktionshastighet och framtida transaktionstillväxt.
  • Detta kan också göras från databasens ände:
    • Övervaka databasen och utvärdera antalet transaktioner som sker under dagen. Detta kan göras genom att fråga pgcatalog-tabeller som pg_stat_user_tables.

    • Utvärdera antalet valarkivfiler som genereras per dag

    • Övervaka för att förstå hur kontrollpunkterna fungerar genom att aktivera parametern 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
    • Förstå om den aktuella kontrollpunktskonfigurationen är tillräckligt bra för databasen. Konfigurera checkpoint_warning-parametern (som standard konfigurerad till 30 sekunder) för att se nedanstående varningar i postgres-loggfilerna.

      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".

Vad betyder varningen ovan?

Kontrollpunkter inträffar i allmänhet när loggfiler till ett värde av max_wal_size (1 GB som standard vilket innebär 64 WAL-filer) fylls upp eller när checkpoint_timeout (var 5:e minut varje standard) nås. Ovanstående varningsmedel som konfigurerats max_wal_size är inte adekvat och kontrollpunkterna inträffar var 11:e sekund, vilket i sin tur betyder att 64 WAL-filer i PG_WAL-katalogen fylls på bara 11 sekunder, vilket är för ofta. Med andra ord, om det är mindre frekventa transaktioner, kommer kontrollpunkterna att inträffa var 5:e minut. Så, som tipset antyder, öka parametern max_wal_size till ett högre värde, parametern max_min_size kan ökas till samma eller mindre än tidigare.

En annan kritisk parameter att överväga ur I/O-prestandaperspektiv är checkpoint_completion_target som som standard är konfigurerad till 0.5.

checkpoint_completion_target =0,5 x checkpoint_timeout =2,5 minuter

Det betyder att kontrollpunkter har 2,5 minuter på sig att synkronisera de smutsiga blocken till disken. Räcker 2,5 minuter? Det måste utvärderas. Om antalet smutsiga block som ska skrivas är mycket högt kan 2,5 minuter verka väldigt aggressivt och det är då en I/O-spik kan observeras. Konfigurering av parametern completion_target måste göras baserat på värdena för max_wal_size och checkpoint_timeout. Om dessa parametrar höjs till ett högre värde, överväg att höja checkpoint_completion_target i enlighet därmed.

VAKUUM, ANALYSE (med FILLFACTOR)

VACUUM är en av de mest kraftfulla funktionerna i PostgreSQL. Den kan användas för att ta bort uppblåsthet (fragmenterat utrymme) i tabeller och index, och genereras av transaktioner. Databasen måste utsättas för dammsugning regelbundet för att säkerställa hälsosamt underhåll och bättre prestanda. Återigen, att inte dammsuga databasen regelbundet kan leda till allvarliga prestandaproblem. ANALYSE måste utföras tillsammans med VACUUM (VACUUM ANALYZE) för att säkerställa uppdaterad statistik för frågeplaneraren.

VAKUUMANALYS kan utföras på två sätt:manuellt, automatiskt eller båda. I en realtidsproduktionsmiljö är det i allmänhet både och. Automatiskt VAKUUM aktiveras av parametern "autovakuum" som som standard är konfigurerat till "på". Med autovakuum aktiverat börjar PostgreSQL automatiskt dammsuga tabellerna med jämna mellanrum. De kandidatbord som behöver dammsugas plockas upp av autovakuumprocesser baserat på olika tröskelvärden som ställs in av olika autovakuum* parametrar, dessa parametrar kan justeras/justeras för att säkerställa att uppblåsningar av tabellerna rensas med jämna mellanrum. Låt oss titta på några parametrar och deras användning -

Autovakuumparametrar

autovacuum=on Denna parameter används för att aktivera/avaktivera autovakuum. Standard är "på".
log_autovacuum_min_duration =-1 Loggar varaktigheten av autovakuumprocessen. Detta är viktigt för att förstå hur länge autovakuumprocessen pågick.
autovacuum_max_workers =3 Antal autovakuumprocesser som behövs. Detta beror på hur aggressiva databastransaktioner är och hur många processorer du kan erbjuda för autovakuumprocesser.
autovacuum_naptime =1 min Autovakuumvilotid mellan autovakuumkörningar.

Parametrar som definierar tröskeln för att autovakuumprocessen ska starta

Autovakuumjobb startar när en viss tröskel nås. Nedan finns parametrarna som kan användas för att ställa in ett visst tröskelvärde, baserat på vilket autovakuumprocessen kommer att starta.

autovacuum_vacuum_threshold =50 Tabell kommer att dammsugas när minst 50 rader kommer att uppdateras / raderas i en tabell.
autovacuum_analyze_threshold =50 Tabellen kommer att analyseras när minst 50 rader kommer att uppdateras / raderas i en tabell.
autovacuum_vacuum_scale_factor =0,2 Tabellen kommer att dammsugas när minst 20 % av raderna uppdateras/raderas i en tabell.
autovacuum_analyze_scale_factor =0,1 Tabellen kommer att dammsugas när minst 10 % av raderna uppdateras/raderas i en tabell.

Parametrar över tröskelvärdet kan modifieras baserat på databasbeteende. DBA:er kommer att behöva analysera och identifiera de heta tabellerna och se till att dessa tabeller dammsugs så ofta som möjligt för att säkerställa bra prestanda. Att komma fram till ett visst värde för dessa parametrar kan vara en utmaning i en miljö med höga transaktioner, där dataförändringar sker varje sekund. Många gånger märkte jag att autovakuumprocesser tar ganska lång tid att slutföra, vilket slutar med att det förbrukar för mycket resurser i produktionssystemen.

Jag skulle föreslå att du inte är helt beroende av autovakuumprocessen, det bästa sättet är att schemalägga ett nattligt VAKUUMANALYS-jobb så att belastningen på autovakuum minskar. Till att börja med, överväg att manuellt dammsuga stora bord med en hög transaktionshastighet.

VAKUUM FULL

VACUUM FULL hjälper till att återta det uppsvällda utrymmet i tabellerna och indexen. Det här verktyget kan inte användas när databasen är online eftersom den låser tabellen. Tabeller får endast utsättas för VAKUUM FULL när applikationerna är avstängda. Index kommer också att omorganiseras tillsammans med tabeller under VACUUM FULL.

Låt oss ta en titt på effekten av VACUUM ANALYZE

Uppsvällningar:Hur identifierar jag uppsvällningar? När genereras uppblåsthet?

Här är några tester:

Jag har en tabell på 1 GB med 10 miljoner rader.

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

 ?column? 
----------------
        1

postgres=# select count(*) From pgbench_accounts ;
  count   
-----------------
 10000000

Låt oss titta på effekten av uppblåsthet på en enkel fråga:välj * från pgbench_accounts;

Nedan är förklarande plan för frågan:

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

Låt oss nu uppdatera alla rader i tabellen och se effekten av ovanstående SELECT-fråga.

postgres=# update pgbench_accounts set abalance=1;
UPDATE 10000000

postgres=# select count(*) From pgbench_accounts ;
  count   
-----------------
 10000000

Nedan är EXPLAIN PLAN för frågan efter UPDATE-exekveringen.

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 storlek ökade till 2 GB efter UPPDATERING

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

 ?column? 
-----------------
        2

Om du kan observera och jämföra kostnadssiffrorna för den tidigare EXPLAIN PLAN, är det en enorm skillnad. Kostnaden har ökat med stor marginal. Ännu viktigare om du observerar noggrant, antalet rader (drygt 19 miljoner) som skannas efter UPPDATERING är högre, vilket är nästan två gånger det faktiska befintliga raderna (10 miljoner). Det betyder att antalet uppsvällda rader är 9+ miljoner och den faktiska tiden ökade också och exekveringstiden ökade från 1,4 sekunder till 1,9 sekunder.

Så det är effekten av att inte dammsuga TABELLEN efter UPPDATERING. Ovanstående EXPLAIN PLAN-siffror betyder exakt att tabellen är uppsvälld.

Hur identifierar man om bordet är uppsvällt? Använd 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

Ovanstående siffra indikerar att halva tabellen är uppsvälld.

Låt oss VAKUUMANALYSERA tabellen och se effekten 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 VAKUUMANALYS har kostnadstalen minskat. Nu visar antalet skannade rader uppemot 10 miljoner, även den faktiska tiden och exekveringstiden förändrades inte mycket. Det beror på att även om uppblåsningarna i bordet har försvunnit, förblir storleken på bordet som ska skannas densamma. Nedan är den pgstattupla utgången efter VAKUUMANALYS.

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

Ovanstående siffra indikerar att alla uppsvällningar (döda tuplar) har försvunnit.

Låt oss titta på effekten av VACUUM FULL ANALYSE och se vad som händer:

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

Om du observerar, liknar den faktiska tiden och exekveringstiden siffrorna före UPPDATERING. Dessutom har bordets storlek nu minskat från 2 GB till 1 GB.

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

 ?column? 
-----------------
        1

Det är effekten av VACUUM FULL.

FYLLFAKTOR

FILLFACTOR är ett mycket viktigt attribut som kan göra verklig skillnad för databasunderhållsstrategin på tabell- och indexnivå. Detta värde indikerar mängden utrymme som ska användas av INFOGARNA i ett datablock. FILLFACTOR-värdet är som standard 100 %, vilket betyder att INSERTs kan använda allt tillgängligt utrymme i ett datablock. Det betyder också att inget utrymme finns tillgängligt för UPPDATERINGAR. Detta värde kan sänkas till ett visst värde för kraftigt uppdaterade tabeller.

Denna parameter kan konfigureras för varje tabell och ett index. Om FILLFACTOR är konfigurerat till det optimala värdet kan du se verklig skillnad i VAKUUM-prestanda och frågeprestanda också. Kort sagt, optimala FILLFACTOR-värden säkerställer att onödigt antal block inte allokeras.

Låt oss titta på samma exempel ovan -

Tabellen har en miljon rader

postgres=# select count(*) From pgbench_accounts ;
  count   
-----------------
 10000000

Före uppdatering är tabellens storlek 1 GB

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

?column? 
--------
   1

postgres=# update pgbench_accounts set abalance=1;
UPDATE 10000000

Efter uppdateringen ökade tabellens storlek till 2 GB efter UPPDATERING

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

?column? 
---------
    2

Det betyder att antalet block som tilldelats bordet har ökat med 100 %. Om FILLFACTOR konfigurerades kanske storleken på tabellen inte har ökat med den marginalen.

Hur vet man vilket värde som ska konfigureras till FILLFACTOR?

Allt beror på vilka kolumner som uppdateras och storleken på de uppdaterade kolumnerna. I allmänhet skulle det vara bra att utvärdera FILLFACTOR-värdet genom att testa det i UAT-databaser. Om kolumnerna som uppdateras är säg 10 % av hela tabellen, överväg att konfigurera fillfactor till 90 % eller 80 %.

Viktig anmärkning:
Om du ändrar FILLFACTOR-värdet för den befintliga tabellen med data, måste du göra en VACUUM FULL eller en omorganisering av tabellen för att säkerställa att FILLFACTOR-värdet är aktivt för befintliga data.

DAMSUGINGSTIPS

  • Som sagt ovan, överväg att köra VACUUM ANALYZE-jobbet manuellt varje natt på de hårt använda borden även när autovacuum är aktiverat.
  • Överväg att köra VACUUM ANALYZE på tabeller efter mass-INSERT. Detta är viktigt eftersom många tror att dammsugning kanske inte behövs efter INSERT.
  • Övervaka för att säkerställa att mycket aktiva tabeller dammsugs regelbundet genom att fråga tabellen pg_stat_user_tables.
  • Använd pg_stattuple bidragsmodul för att identifiera storleken på det uppsvällda utrymmet inom tabellsegmenten.
  • VACUUM FULL-verktyget kan inte användas på produktionsdatabassystem. Överväg att använda verktyg som pg_reorg eller pg_repack som hjälper till att omorganisera tabeller och index online utan lås.
  • Se till att AUTOVACUUM-processen körs under en längre tid under kontorstid (hög trafik).
  • Aktivera parametern log_autovacuum_min_duration för att logga tidpunkterna och varaktigheten för AUTOVACUUM-processer.
  • Viktigt, se till att FILLFACTOR är konfigurerad till ett optimalt värde på tabeller och index med höga transaktioner.
Ladda ner Whitepaper Today PostgreSQL Management &Automation med ClusterControlLäs om vad du behöver veta för att distribuera, övervaka, hantera och skala PostgreSQLDladda Whitepaper

Andra I/O-problem

Disksortering

Frågor som utför sortering är en annan vanlig företeelse i realtidsproduktionsdatabaser och de flesta av dessa kan inte undvikas. Frågor som använder klausuler som GROUP BY, ORDER BY, DISTINCT, CREATE INDEX, VACUUM FULL etc. utför sortering och sorteringen kan ske på disk. Sortering sker i minnet om urvalet och sorteringen sker utifrån indexerade kolumner. Det är här sammansatta index spelar en nyckelroll. Index cachas aggressivt i minnet. Annars, om det uppstår ett behov av att sortera data på disken, skulle prestandan sakta ner drastiskt.

För att säkerställa att sortering sker i minnet kan parametern work_mem användas. Denna parameter kan konfigureras till ett värde så att hela sorteringen kan göras i minnet. Kärnfördelen med denna parameter är att den, förutom att konfigurera den i postgresql.conf, även kan konfigureras på sessionsnivå, användarnivå eller databasnivå. Hur mycket ska work_mem-värdet vara? Hur vet man vilka frågor som utför disksortering? Hur övervakar man frågor som utför disksortering på en produktionsdatabas i realtid?

Svaret är - konfigurera log_temp_files parameter till ett visst värde. Värdet är i byte, ett värde på 0 loggar alla temporära filer (tillsammans med deras storlekar) som genereras på disken på grund av disksortering. När parametern är konfigurerad kommer du att kunna se följande meddelanden i loggfilerna

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);

Ovanstående meddelande betyder att CREATE INDEX-frågan utförde disksortering och har genererat en fil med storleken 200425472 byte som är 191+ MB. Det betyder exakt att parametern work_mem måste konfigureras till 191+ MB eller högre för att just den här frågan ska kunna utföra minnessortering.

Tja, för applikationsfrågorna kan parametern work_mem endast konfigureras på användarnivå. Innan du gör det, akta dig för antalet anslutningar som användaren gör till databasen och antalet sorteringsfrågor som exekveras av den användaren. Eftersom PostgreSQL försöker allokera work_mem till varje process (utför sortering) i varje anslutning, vilket potentiellt skulle kunna svälta ut minnet på databasservern.

Layout för databasfilsystem

Att designa en effektiv och prestandabefrämjande layout för databasfilsystem är viktigt ur prestanda- och skalbarhetsperspektiv. Viktigt är att detta inte är beroende av databasens storlek. Generellt sett är uppfattningen att stora databaser kommer att behöva högpresterande diskarkitektur, vilket INTE är sant. Även om databasstorleken är 50 GB kan du behöva en bra diskarkitektur. Och detta kanske inte är möjligt utan att det medför extra kostnader.

Här är några TIPS för detsamma:

  • Se till att databasen har flera tabellutrymmen, med tabeller och index grupperade baserat på transaktionshastigheterna.
  • Tabellutrymmet måste placeras över flera diskfilsystem för balanserad I/O. Detta säkerställer också att flera processorer kommer in för att utföra transaktioner över flera diskar.
  • Överväg att placera katalogen pg_xlog eller pg_wal på en separat disk i en databas med höga transaktioner.
  • Se till att *_cost-parametrar är konfigurerade baserat på infrastrukturen
  • Använd iostat, mpstat och andra I/O-övervakningsverktyg för att förstå I/O-statistiken över alla diskar och utforma/hantera databasobjekten därefter.

PostgreSQL på molnet

Infrastruktur är avgörande för god databasprestanda. Prestandatekniska strategier skiljer sig beroende på infrastruktur och miljö. Särskild försiktighet måste tas för PostgreSQL-databaser som är värd i molnet. Prestandabenchmarking för databaser som finns på fysiska barebone-servrar i ett lokalt datacenter kan skilja sig helt från databaser som finns i det offentliga molnet.

I allmänhet kan molninstanser vara lite långsammare och riktmärken skiljer sig med stor marginal, särskilt när det gäller I/O. Utför alltid I/O-latenskontroller innan du väljer / bygger en molninstans. Till min förvåning lärde jag mig att prestandan för molninstanser kan variera beroende på regioner, även om de kommer från samma molnleverantör. För att förklara detta ytterligare kan en molninstans med samma specifikationer byggda i två olika regioner ge dig olika prestandaresultat.

Massdataladdning

Offline-bulkdataladdningsoperationer är ganska vanliga i databasvärlden. De kan generera betydande I/O-belastning, vilket i sin tur saktar ner dataladdningsprestandan. Jag har ställts inför sådana utmaningar i min erfarenhet som DBA. Ofta blir dataladdningen fruktansvärt långsam och måste justeras. Här är några tips. Tänk på att dessa endast gäller offline-dataladdningsoperationer och kan inte övervägas för dataladdning i live-produktionsdatabasen.

  • Eftersom de flesta av dataladdningsoperationerna utförs under öppet kontorstid, se till att följande parametrar är konfigurerade under dataladdningen -
    • Konfigurera kontrollpunktsrelaterade värden som är tillräckligt stora så att kontrollpunkter inte orsakar några prestandaproblem.
    • Stäng av full_page_write
    • Stäng av valarkivering
    • Konfigurera synchronous_commit-parametern till "av"
    • Släpp begränsningar och index för de tabeller som utsätts för databelastningen (Begränsningar och index kan återskapas efter dataladdningen med ett större work_mem-värde)
    • Om du laddar data från en CSV-fil kan större maintenance_work_mem ge dig bra resultat.
    • Även om det kommer att vara en betydande prestandafördel, stäng INTE av fsync-parametern eftersom det kan leda till datakorruption.

TIPS för analys av molnprestanda

  • Utför grundliga I/O-latenstest med pgbench. Enligt min erfarenhet hade jag ganska vanliga prestandaresultat när jag gjorde disklatenskontroller som en del av TPS-utvärdering. Det fanns problem med cacheprestanda på vissa offentliga molninstanser. Detta hjälper dig att välja lämpliga specifikationer för den molninstans som valts för databaserna.
  • Molninstanser kan fungera olika från region till region. En molninstans med vissa specifikationer i en region kan ge olika prestandaresultat jämfört med en molninstans med samma specifikationer i en annan region. Mina pgbench-tester som utfördes på flera molninstanser (alla samma specifikationer med samma molnleverantör) över olika regioner gav mig olika resultat på några av dem. Detta är viktigt, särskilt när du migrerar till molnet.
  • Frågeprestanda i molnet kan behöva en annan inställningsmetod. DBA:er måste använda *_cost-parametrar för att säkerställa att sunda frågekörningsplaner genereras.

Verktyg för att övervaka PostgreSQL-prestanda

Det finns olika verktyg för att övervaka PostgreSQL-prestanda. 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.


  1. SQL CREATE TABLE Syntax – Listad av DBMS

  2. Rekursiv fråga i Oracle

  3. Oracle UTL_HTTP Post Multipart/Form-Data (JSON &ZIP) Exempel

  4. Söka Microsoft Access-data med Elasticsearch