PostgreSQL je jednou z nejpopulárnějších databází s otevřeným zdrojovým kódem na světě a má úspěšné implementace v několika kriticky důležitých prostředích v různých doménách s využitím špičkových aplikací OLTP v reálném čase provádějících miliony a miliardy transakcí denně. PostgreSQL I/O je poměrně spolehlivý, stabilní a výkonný na téměř jakémkoli hardwaru, včetně cloudu.
Aby bylo zajištěno, že databáze budou fungovat v očekávaném měřítku s očekávanou dobou odezvy, je potřeba určité výkonnostní inženýrství. Dosažení dobrého výkonu databáze závisí na různých faktorech. Výkon databáze se může zhoršit z různých důvodů, jako je dimenzování infrastruktury, neefektivní strategie údržby databáze, špatný kód SQL nebo špatně nakonfigurované databázové procesy, které nevyužívají všechny dostupné zdroje – CPU, paměť, šířku pásma sítě a diskové I/O.
Co může způsobit snížení výkonu databáze?
- Špatně napsané dotazy se špatnými spojeními, logikou atd., které zabírají hodně CPU a paměti
- Dotazy provádějící celoplošné skenování na velkých stolech kvůli nesprávnému indexování
- Špatná údržba databáze bez řádných statistik
- Neefektivní plánování kapacit, které má za následek nedostatečně dimenzovanou infrastrukturu
- Nesprávný logický a fyzický design
- Neexistuje žádné sdružování připojení, což způsobuje, že aplikace vytvářejí obrovské množství připojení nekontrolovatelným způsobem.
To je tedy mnoho potenciálních oblastí, které mohou způsobit problémy s výkonem. Jednou z významných oblastí, na kterou bych se chtěl v tomto blogu zaměřit, je to, jak vyladit výkon I/O (vstup/výstup) PostgreSQL. Vyladění vstupních/výstupních operací PostgreSQL je nezbytné, zejména v prostředí s vysokými transakcemi, jako je OLTP nebo v prostředí datových skladů s komplexní analýzou dat na velkých souborech dat.
Problémy s výkonem databáze jsou ve většině případů způsobeny především vysokým I/O. To znamená, že databázové procesy tráví více času zápisem nebo čtením z disku. Jakákoli operace s daty v reálném čase je vázána na I/O, je nutné zajistit, aby databáze byla I/O vyladěna. V tomto blogu se zaměřím na běžné I/O problémy, se kterými se PostgreSQL databáze mohou setkat v produkčním prostředí v reálném čase.
Ladění PostgreSQL I/O
Ladění PostgreSQL I/O je nezbytné pro vybudování vysoce výkonné a škálovatelné databázové architektury. Podívejme se na různé faktory ovlivňující výkon I/O:
- Indexování
- Rozdělení
- Kontrolní body
- VAKUUM, ANALÝZA (pomocí FILLFACTORU)
- Další problémy I/O
- PostgreSQL I/O v cloudu
- Nástroje
Indexování
Indexování je jednou ze základních technik ladění, která hraje zásadní roli při zlepšování výkonu I/O databáze. To platí opravdu pro každou databázi. PostgreSQL podporuje různé typy indexů, které mohou do značné míry urychlit operace čtení, což přináší rozšířenou škálovatelnost aplikací. I když je vytváření indexů poměrně jednoduché a přímočaré, je nezbytné, aby správci databází a vývojáři věděli, jaký typ indexu zvolit a v jakých sloupcích. Ta je založena na různých faktorech, jako je složitost dotazu, datový typ, kardinalita dat, objem zápisů, velikost dat, architektura disku, infrastruktura (veřejný cloud, privátní cloud nebo on-premises) atd.
Zatímco indexování může výrazně zlepšit výkon při čtení dotazů, může také zpomalit zápisy narážející do indexovaných sloupců. Podívejme se na příklad:
Vliv indexů na operace READ
Tabulka s názvem emp s přibližně 1 milionem řádků.
ČTĚTE Výkon bez indexu
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
ČTĚTE Výkon s indexem
Umístíme index na sloupec eid a uvidíme rozdíl
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?
Indexování je tedy důležité.
Vliv indexů na operace WRITE
Indexy zpomalují výkon zápisu. Zatímco indexy mají dopad na všechny typy operací zápisu, podívejme se na analýzu dopadu indexů na INSERT
Vložení 1 milionu řádků do tabulky bez 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
Vložení stejného 1 milionu řádků s indexem
Nejprve vytvořte index
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
Jak tedy můžeme pozorovat, doba INSERT se zvýšila o 80 % pouze s jedním indexem a dokončení může trvat mnohem déle, pokud existuje více indexů. Může to být ještě horší, když existují indexy založené na funkcích. S tím musí DBA žít! Indexy zvýší výkon zápisu. Existují způsoby, jak tento problém vyřešit, což je závislé na architektuře disku. Pokud databázový server používá více diskových souborových systémů, pak lze indexy a tabulky umístit do více tabulkových prostorů umístěných na více diskových souborových systémech. Tímto způsobem lze dosáhnout lepšího I/O výkonu.
TIPY pro správu indexu
- Pochopte potřebu indexů. Inteligentní indexování je klíčové.
- Vyhněte se vytváření více indexů a rozhodně žádné zbytečné indexy, to může skutečně snížit výkon zápisu.
- Monitorujte využití indexů a zrušte všechny nepoužívané indexy.
- Když jsou indexované sloupce vystaveny změnám dat, indexy jsou také nafouklé. Pravidelně tedy reorganizujte indexy.
Rozdělení
Efektivní strategie dělení může do značné míry snížit problémy s výkonem I/O. Velké tabulky lze dělit na oddíly na základě obchodní logiky. PostgreSQL podporuje dělení tabulek. Přestože v současné době plně nepodporuje všechny funkce, může pomoci pouze s některými případy použití v reálném čase. V PostgreSQL jsou rozdělené podřízené tabulky zcela individuální vzhledem k hlavní tabulce, což je úzké místo. Např. omezení vytvořená v hlavní tabulce nelze automaticky zdědit do podřízených tabulek.
Z hlediska vyvážení I/O však může rozdělení skutečně pomoci. Všechny podřízené oddíly lze rozdělit do více tabulkových prostorů a diskových souborových systémů. Dotazy s časovým rozsahem v klauzuli „kde“ zasahující do tabulky, rozdělené na základě časového rozsahu, mohou těžit z rozdělení pouhým skenováním jednoho nebo dvou oddílů namísto celé tabulky.
Kontrola
Kontrolní body definují konzistentní stav databáze. Jsou kritické a je důležité, aby se kontrolní body objevovaly dostatečně pravidelně, aby bylo zajištěno, že změny dat budou trvale uloženy na disk a databáze bude po celou dobu v konzistentním stavu. Jak již bylo řečeno, nesprávná konfigurace kontrolních bodů může vést k problémům s výkonem I/O. DBA musí být pečliví, pokud jde o konfiguraci kontrolních bodů, aby zajistili, že nedojde ke špičce I/O a také to závisí na tom, jak kvalitní jsou disky a jak dobře je navrženo rozložení datových souborů.
Co dělá kontrolní bod?
Jednoduše řečeno, kontrolní body zajistí:
- Všechna potvrzená data jsou zapsána do datových souborů na disku.
- Soubory ucpání jsou aktualizovány se stavem odevzdání.
- Soubory protokolu transakcí v adresáři pg_xlog (nyní pg_wal) jsou recyklovány.
To vysvětluje, jak intenzivní jsou kontrolní body I/O. V postgresql.conf jsou parametry, které lze nakonfigurovat / vyladit tak, aby řídily chování kontrolních bodů, a tyto parametry jsou max_wal_size, min_wal_size, checkpoint_timeout a checkpoint_completion_target. Tyto parametry rozhodnou, jak často by se měly kontrolní body vyskytovat a za jak dlouho musí kontrolní body dokončit.
Jak pochopit, jaká konfigurace je lepší pro kontrolní body? Jak je naladit?
Zde je několik tipů:
- Vyhodnoťte databázi TPS. Vyhodnoťte celkový objem transakcí vyskytujících se v databázi za pracovní den a také zjistěte, kdy do databáze zasáhne nejvyšší počet transakcí.
- Pravidelně diskutujte s vývojáři aplikací a dalšími technickými týmy, abyste porozuměli statistice rychlosti transakcí v databázi a také budoucímu růstu transakcí.
- To lze provést i z konce databáze:
-
Sledujte databázi a vyhodnocujte počet transakcí, ke kterým během dne dochází. To lze provést dotazem na tabulky pgcatalog jako pg_stat_user_tables.
-
Vyhodnoťte počet archivních souborů wal vygenerovaných za den
-
Povolením parametru log_checkpoints
sledujte, jak fungují kontrolní body2018-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
-
Pochopte, zda je aktuální konfigurace kontrolního bodu pro databázi dostatečně dobrá. Nakonfigurujte parametr checkpoint_warning (ve výchozím nastavení na 30 sekund), abyste viděli níže uvedená varování v souborech protokolu postgres.
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".
-
Co znamená výše uvedené varování?
Kontrolní body se obecně vyskytují vždy, když je zaplněna max_wal_size (1 GB ve výchozím nastavení, což znamená 64 souborů WAL) v hodnotě souborů protokolů nebo když je dosaženo checkpoint_timeout (každých 5 minut při každém výchozím nastavení). Výše uvedené varování znamená, že nakonfigurovaná max_wal_size není adekvátní a kontrolní body se vyskytují každých 11 sekund, což znamená, že 64 souborů WAL v adresáři PG_WAL se zaplní za pouhých 11 sekund, což je příliš časté. Jinými slovy, pokud jsou transakce méně časté, pak se kontrolní body objeví každých 5 minut. Takže, jak naznačuje nápověda, zvyšte parametr max_wal_size na vyšší hodnotu, parametr max_min_size lze zvýšit na stejnou nebo nižší než předchozí.
Dalším kritickým parametrem, který je třeba zvážit z hlediska výkonu I/O, je checkpoint_completion_target, který je ve výchozím nastavení nakonfigurován na 0,5.
checkpoint_completion_target =0,5 x checkpoint_timeout =2,5 minuty
To znamená, že kontrolní body mají 2,5 minuty na synchronizaci špinavých bloků na disk. Stačí 2,5 minuty? To je potřeba vyhodnotit. Pokud je počet nečistých bloků, které mají být zapsány, velmi vysoký, pak se 2,5 minuty může zdát velmi velmi agresivní a tehdy lze pozorovat I/O špičku. Konfigurace parametru complete_target musí být provedena na základě hodnot max_wal_size a checkpoint_timeout. Pokud jsou tyto parametry zvýšeny na vyšší hodnotu, zvažte odpovídající zvýšení checkpoint_completion_target.
VAKUUM, ANALÝZA (pomocí FILLFACTORU)
VACUUM je jednou z nejvýkonnějších funkcí PostgreSQL. Lze jej použít k odstranění bloatů (fragmentovaného prostoru) v tabulkách a indexech a je generován transakcemi. Databáze musí být pravidelně VAKUOVÁNA, aby byla zajištěna zdravá údržba a lepší výkon. Opět platí, že pravidelné nevysávání databáze může vést k vážným problémům s výkonem. ANALYZE musí být provedena společně s VACUUM (VACUUM ANALYZE), aby byla zajištěna aktuální statistika pro plánovač dotazů.
VACUUM ANALYZE může být provedena dvěma způsoby:ručně, automaticky nebo oběma způsoby. V produkčním prostředí v reálném čase je to obecně obojí. Automatic VACUUM je povoleno parametrem “autovacuum”, který je standardně nastaven na “on”. S povoleným automatickým vysáváním PostgreSQL automaticky začne pravidelně vysávat tabulky. Kandidátské stoly, které potřebují vysát, jsou sbírány procesy autovakuování na základě různých prahových hodnot nastavených různými parametry autovakua*, tyto parametry lze vyladit/vyladit, aby se zajistilo, že nafouknutí ze stolů bude pravidelně odstraňováno. Podívejme se na některé parametry a jejich použití -
Parametry automatického vakua
autovacuum=on | Tento parametr se používá k povolení / zakázání automatického vakua. Výchozí hodnota je „on“. |
log_autovacuum_min_duration =-1 | Zaznamenává dobu trvání procesu autovakuování. To je důležité pro pochopení toho, jak dlouho proces autovakuování běžel. |
autovacuum_max_workers =3 | Počet potřebných procesů autovakuování. To závisí na tom, jak agresivní databázové transakce jsou a kolik CPU můžete nabídnout pro procesy autovakuování. |
autovacuum_naptime =1 min | Doba odpočinku v automatickém vakuu mezi běhy automatického vakua. |
Parametry definující práh pro spuštění procesu Autovakuum
Úloha(y) automatického vakuování se spustí, když je dosaženo určité prahové hodnoty. Níže jsou uvedeny parametry, které lze použít k nastavení určité prahové hodnoty, na jejímž základě se spustí proces autovakuování.
autovacuum_vacuum_threshold =50 | Tabulka bude vakuována, když bude aktualizováno/smazáno minimálně 50 řádků v tabulce. |
autovacuum_analyze_threshold =50 | Tabulka bude analyzována, když bude aktualizováno/smazáno minimálně 50 řádků v tabulce. |
autovacuum_vacuum_scale_factor =0,2 | Tabulka bude vysáta, když bude v tabulce aktualizováno/smazáno minimálně 20 % řádků. |
autovacuum_analyze_scale_factor =0,1 | Tabulka bude vakuována, když bude aktualizováno/smazáno minimálně 10 % řádků v tabulce. |
Nadprahové parametry lze upravit na základě chování databáze. DBA budou muset analyzovat a identifikovat horké stoly a zajistit, aby tyto stoly byly vysávány co nejčastěji, aby byl zajištěn dobrý výkon. Dosažení určité hodnoty těchto parametrů by mohlo být problémem v prostředí s vysokými transakcemi, kde ke změnám dat dochází každou sekundu. Mnohokrát jsem si všiml, že proces autovakuování trvá poměrně dlouho, než se dokončí, což ve výsledku spotřebovává příliš mnoho zdrojů v produkčních systémech.
Navrhoval bych nezáviset zcela na procesu autovakua, nejlepším způsobem je naplánovat noční práci VACUUM ANALYZE tak, aby se zátěž autovakuem snížila. Pro začátek zvažte ruční VAKUOVÁNÍ velkých stolů s vysokou mírou transakcí.
VAKUUM PLNÉ
VACUUM FULL pomáhá získat zpět přeplněné místo v tabulkách a indexech. Tento nástroj nelze použít, když je databáze online, protože zamyká tabulku. Stoly musí být vystaveny VACUUM FULL pouze při vypnutí aplikací. Indexy budou také reorganizovány spolu s tabulkami během VACUUM FULL.
Pojďme se podívat na dopad VACUUM ANALYZE
Nafouknutí:Jak identifikovat nadýmání? Kdy se generují nadýmání?
Zde je několik testů:
Mám tabulku o velikosti 1 GB s 10 miliony řádků.
postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
----------------
1
postgres=# select count(*) From pgbench_accounts ;
count
-----------------
10000000
Podívejme se na dopad nadýmání na jednoduchý dotaz:vyberte * z pgbench_accounts;
Níže je plán vysvětlení pro dotaz:
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
Nyní aktualizujme všechny řádky v tabulce a podívejme se na dopad výše uvedeného dotazu SELECT.
postgres=# update pgbench_accounts set abalance=1;
UPDATE 10000000
postgres=# select count(*) From pgbench_accounts ;
count
-----------------
10000000
Níže je EXPLAIN PLAN provádění dotazu po UPDATE.
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
Velikost tabulky se po UPDATE
zvýšila na 2 GBpostgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
-----------------
2
Pokud můžete pozorovat a porovnat čísla nákladů předchozího plánu EXPLAIN PLAN, je v tom obrovský rozdíl. Náklady se zvýšily o velkou rezervu. Ještě důležitější je, pokud budete pozorně sledovat, počet řádků (něco přes 19 milionů) skenovaných po AKTUALIZACI je vyšší, což je téměř dvojnásobek skutečně existujících řádků (10 milionů). To znamená, že počet nafouknutých řádků je 9+ milionů a skutečný čas se také zvýšil a doba provádění se zvýšila z 1,4 sekundy na 1,9 sekundy.
To je tedy dopad nevysávání TABULKY po AKTUALIZACI. Výše uvedená čísla EXPLAIN PLAN přesně znamenají, že stůl je nafouklý.
Jak zjistit, zda je stůl nafouklý? Použijte modul pgstattuple contrib:
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
Výše uvedené číslo znamená, že polovina stolu je nafouknutá.
Pojďme VAKUOVAT ANALÝZU stolu a nyní uvidíme dopad:
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
Po VACUUM ANALYZE se čísla nákladů snížila. Nyní se počet naskenovaných řádků blíží 10 milionům, také skutečný čas a doba provádění se příliš nezměnily. Je to proto, že i když nafouknutí v tabulce zmizelo, velikost tabulky, která má být naskenována, zůstává stejná. Níže je uveden výstup pgstattuple po VACUUM ANALYZE.
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
Výše uvedené číslo znamená, že všechny bloaty (mrtvé n-tice) zmizely.
Podívejme se na dopad VACUUM FULL ANALYZE a uvidíme, co se stane:
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
Pokud pozorujete, skutečný čas a čísla doby provedení jsou podobná číslům před UPDATE. Velikost tabulky se nyní také snížila ze 2 GB na 1 GB.
postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
-----------------
1
To je dopad VACUUM FULL.
FILLFACTOR
FILLFACTOR je velmi důležitý atribut, který může skutečně změnit strategii údržby databáze na úrovni tabulek a indexů. Tato hodnota udává množství místa, které mají být použity INSERTy v datovém bloku. Výchozí hodnota FILLFACTOR je 100 %, což znamená, že INSERT mohou využít veškerý dostupný prostor v datovém bloku. To také znamená, že není k dispozici žádné místo pro AKTUALIZACE. Tato hodnota může být snížena na určitou hodnotu pro silně aktualizované tabulky.
Tento parametr lze nakonfigurovat pro každou tabulku a index. Pokud je FILLFACTOR nakonfigurován na optimální hodnotu, můžete vidět skutečný rozdíl ve výkonu VACUUM a výkonu dotazů. Stručně řečeno, optimální hodnoty FILLFACTOR zajišťují, že nebude alokován zbytečný počet bloků.
Podívejme se na stejný příklad výše -
Tabulka má jeden milion řádků
postgres=# select count(*) From pgbench_accounts ;
count
-----------------
10000000
Před aktualizací je velikost tabulky 1 GB
postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
--------
1
postgres=# update pgbench_accounts set abalance=1;
UPDATE 10000000
Po aktualizaci se velikost tabulky po UPDATE
zvětšila na 2 GBpostgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;
?column?
---------
2
To znamená, že počet bloků přidělených tabulce se zvýšil o 100 %. Pokud byl nakonfigurován FILLFACTOR, velikost tabulky se možná nezvýšila o tento okraj.
Jak zjistit, jakou hodnotu nakonfigurovat pro FILLFACTOR?
Vše závisí na tom, jaké sloupce se aktualizují, a na velikosti aktualizovaných sloupců. Obecně by bylo dobré vyhodnotit hodnotu FILLFACTOR jejím testováním v databázích UAT. Pokud aktualizované sloupce tvoří řekněme 10 % celé tabulky, zvažte konfiguraci fillfactoru na 90 % nebo 80 %.
Důležitá poznámka:
Pokud změníte hodnotu FILLFACTOR pro existující tabulku s daty, budete muset provést VACUUM FULL nebo reorganizaci tabulky, abyste zajistili, že hodnota FILLFACTOR bude platná pro existující data.
TIPY PRO VYSÁVÁNÍ
- Jak bylo uvedeno výše, zvažte ruční spouštění úlohy VACUUM ANALYZE každou noc na silně zatížených stolech, i když je zapnuté automatické vakuování.
- Zvažte spuštění VACUUM ANALYZE na stolech po hromadném INSERT. To je důležité, protože mnozí věří, že po VLOŽENÍCH nemusí být VYSÁVÁNÍ potřeba.
- Monitorujte, abyste zajistili pravidelné vysávání vysoce aktivních tabulek dotazem na tabulku pg_stat_user_tables.
- Použijte modul pg_stattuple contrib k identifikaci velikosti přebytečného prostoru v segmentech tabulky.
- Obslužný program VACUUM FULL nelze použít na produkčních databázových systémech. Zvažte použití nástrojů jako pg_reorg nebo pg_repack, které pomohou reorganizovat tabulky a indexy online bez zámků.
- Zajistěte, aby proces AUTOVACUUM běžel delší dobu během pracovních hodin (vysoký provoz).
- Povolte parametr log_autovacuum_min_duration pro protokolování časování a trvání procesů AUTOVACUUM.
- Důležité je, aby byl FILLFACTOR nakonfigurován na optimální hodnotu v tabulkách a indexech s vysokými transakcemi.
Jiné I/O problémy
Řazení disků
Dotazy provádějící třídění jsou dalším běžným jevem v produkčních databázích v reálném čase a většině z nich se nelze vyhnout. Dotazy používající klauzule jako GROUP BY, ORDER BY, DISTINCT, CREATE INDEX, VACUUM FULL atd. provádějí třídění a třídění může probíhat na disku. Řazení probíhá v paměti, pokud se výběr a řazení provádí na základě indexovaných sloupců. Zde hrají klíčovou roli složené indexy. Indexy jsou agresivně ukládány do mezipaměti. V opačném případě, pokud by vznikla potřeba třídit data na disku, by se výkon drasticky zpomalil.
Chcete-li zajistit, aby třídění probíhalo v paměti, lze použít parametr work_mem. Tento parametr lze nakonfigurovat na takovou hodnotu, aby bylo možné celé řazení provést v paměti. Hlavní výhodou tohoto parametru je, že kromě konfigurace v postgresql.conf jej lze konfigurovat také na úrovni relace, na úrovni uživatele nebo na úrovni databáze. Kolik by měla být hodnota work_mem? Jak zjistit, které dotazy provádějí třídění disku? Jak monitorovat dotazy provádějící třídění disků v produkční databázi v reálném čase?
Odpověď zní - nakonfigurujte parametr log_temp_files na určitou hodnotu. Hodnota je v bajtech, hodnota 0 zaznamenává všechny dočasné soubory (spolu s jejich velikostmi) vygenerované na disku kvůli třídění disku. Jakmile je parametr nakonfigurován, budete moci vidět následující zprávy v souborech protokolu
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);
Výše uvedená zpráva znamená, že dotaz CREATE INDEX prováděl třídění disku a vygeneroval soubor o velikosti 200425472 bajtů, což je 191+ MB. To přesně znamená, že parametr work_mem musí být nakonfigurován na 191+ MB nebo více, aby tento konkrétní dotaz provedl třídění paměti.
No, pro aplikační dotazy lze parametr work_mem konfigurovat pouze na uživatelské úrovni. Než tak učiníte, dejte si pozor na počet připojení, která uživatel vytváří s databází, a na počet třídicích dotazů, které tento uživatel provádí. Protože PostgreSQL se snaží přidělit work_mem každému procesu (provádějícímu řazení) v každém připojení, což by mohlo potenciálně vyhladovět paměť na databázovém serveru.
Rozvržení systému souborů databáze
Navrhování efektivního a výkon vedoucího rozložení databázového souborového systému je důležité z hlediska výkonu a škálovatelnosti. Důležité je, že to nezávisí na velikosti databáze. Obecně platí, že velké databáze budou potřebovat vysoce výkonnou diskovou architekturu, což NENÍ pravda. I když je velikost databáze 50 GB, možná budete potřebovat dobrou architekturu disku. A to nemusí být možné bez dodatečných nákladů.
Zde je několik TIPŮ pro totéž:
- Zajistěte, aby databáze obsahovala více tabulkových prostorů s tabulkami a indexy seskupenými podle sazeb transakcí.
- Tabulkový prostor musí být umístěn na více diskových souborových systémech pro vyvážené I/O. To také zajistí, že do hry vstoupí více CPU pro provádění transakcí na více discích.
- Zvažte umístění adresáře pg_xlog nebo pg_wal na samostatný disk v databázi s vysokými transakcemi.
- Zajistěte, aby parametry *_cost byly nakonfigurovány na základě infrastruktury
- Použijte iostat, mpstat a další nástroje pro monitorování I/O, abyste porozuměli statistikám I/O na všech discích a podle toho architekt/spravovali databázové objekty.
PostgreSQL v cloudu
Infrastruktura je kritická pro dobrý výkon databáze. Strategie výkonového inženýrství se liší podle infrastruktury a prostředí. Zvláštní péči je třeba věnovat databázím PostgreSQL hostovaným v cloudu. Srovnávání výkonu pro databáze hostované na fyzických barebone serverech v místním datovém centru se může zcela lišit od databází hostovaných ve veřejném cloudu.
Obecně by cloudové instance mohly být o něco pomalejší a benchmarky se značně liší, zejména pokud jde o I/O. Před výběrem/vytvořením cloudové instance vždy proveďte kontroly I/O latence. K mému překvapení jsem se dozvěděl, že výkon cloudových instancí se může lišit také v závislosti na regionech, i když jsou od stejného poskytovatele cloudu. Abychom to vysvětlili dále, cloudová instance se stejnými specifikacemi ve dvou různých oblastech vám může poskytnout různé výsledky výkonu.
Hromadné načítání dat
Offline operace hromadného načítání dat jsou ve světě databází docela běžné. Mohou generovat značné I/O zatížení, což zase zpomaluje výkon při načítání dat. Ve své zkušenosti jako DBA jsem čelil takovým výzvám. Načítání dat se často strašně zpomaluje a musí se ladit. Zde je několik tipů. Pamatujte, že tyto se vztahují pouze na operace načítání dat offline a nelze je brát v úvahu pro načítání dat do živé produkční databáze.
- Vzhledem k tomu, že většina operací načítání dat se provádí mimo pracovní dobu, zajistěte, aby byly během načítání dat nakonfigurovány následující parametry –
- Nakonfigurujte dostatečně velké hodnoty související s kontrolními body, aby kontrolní body nezpůsobovaly žádné problémy s výkonem.
- Vypněte full_page_write
- Vypněte archivaci wal
- Nakonfigurujte parametr synchronous_commit na „off“
- Zrušte omezení a indexy pro tabulky vystavené zatížení dat (omezení a indexy lze po načtení dat znovu vytvořit s vyšší hodnotou work_mem)
- Pokud provádíte načítání dat ze souboru CSV, větší maintenance_work_mem vám může přinést dobré výsledky.
- Přestože dojde k významnému zvýšení výkonu, NEVYPÍNEJTE parametr fsync, protože by to mohlo vést k poškození dat.
TIPY pro analýzu výkonu cloudu
- Proveďte důkladné testy I/O latence pomocí pgbench. Podle mých zkušeností jsem měl docela běžné výsledky výkonu při provádění kontrol latence disku v rámci hodnocení TPS. U některých instancí veřejného cloudu došlo k problémům s výkonem mezipaměti. To pomůže vybrat vhodné specifikace pro cloudovou instanci vybranou pro databáze.
- Instance cloudu mohou v jednotlivých oblastech fungovat odlišně. Instance cloudu s určitými specifikacemi v oblasti může poskytovat odlišné výsledky výkonu ve srovnání s instancí cloudu se stejnými specifikacemi v jiné oblasti. Moje testy pgbench provedené na více instancích cloudu (všechny stejné specifikace se stejným dodavatelem cloudu) v různých oblastech mi v některých z nich poskytly různé výsledky. To je důležité zejména při migraci do cloudu.
- Výkon dotazů v cloudu může vyžadovat jiný přístup k ladění. DBA budou muset používat parametry *_cost, aby bylo zajištěno generování zdravých plánů provádění dotazů.
Tools to Monitor PostgreSQL Performance
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.