Klassikaline kĂŒsimus, millega arendaja pöördub oma DBA vĂ”i Ă€riomaniku poole â PostgreSQL konsultandi poole, kĂ”lab peaaegu alati ĂŒhtemoodi: âMiks pĂ€ringud töötlevad andmebaasis nii kaua?â
Traditsiooniline pÔhjuste kogum:
- efektiivne algoritm
kui otsustasite teha JOIN mitu CTE paarikĂŒmne tuhande kirje kohta - vakku statistikat
kui tegelik andmete jaotumine tabelis erineb juba oluliselt viimasest ANALYZEâist - ressursside âummistusâ
ja juba ei piisa eraldatud arvutusvĂ”imsusest CPU, pidevalt tĂ”useb gigabaite mĂ€lu vĂ”i kett ei jĂ”ua kĂ”ikide andmebaasi âsoovideâ tĂ€itmisega - blokaadid konkureerivatest protsessidest
Ja kui lukustused on piisavalt keerulised tabamiseks ja analĂŒĂŒsimiseks, siis kĂ”igi teiste jaoks piisab meile pĂ€ringute plaanist, mille saab hankida (muidugi on parem kohe EXPLAIN (ANALYZE, BUFFERS) ...) vĂ”i .
Kuid nagu öeldud sama dokumentatsioonis,
âPlani mĂ”istmine on kunst, ja selle omandamiseks on vajalik teatud kogemusâŠâ
Aga selleta ei ole tarvis, kui kasutada Ôigustatud tööriistu!
Kuidas nÀeb tavaliselt vÀlja pÀringu plaan? Nii:
Index Scan using pg_class_relname_nsp_index on pg_class (actual time=0.049..0.050 rows=1 loops=1)
Index Cond: (relname = $1)
Filter: (oid = $0)
Buffers: shared hit=4
InitPlan 1 (returns $0,$1)
-> Limit (actual time=0.019..0.020 rows=1 loops=1)
Buffers: shared hit=1
-> Seq Scan on pg_class pg_class_1 (actual time=0.015..0.015 rows=1 loops=1)
Filter: (relkind = 'r'::"char")
Rows Removed by Filter: 5
Buffers: shared hit=1vÔi nii:
"Append (cost=868.60..878.95 rows=2 width=233) (actual time=0.024..0.144 rows=2 loops=1)"
" Buffers: shared hit=3"
" CTE cl"
" -> Seq Scan on pg_class (cost=0.00..868.60 rows=9972 width=537) (actual time=0.016..0.042 rows=101 loops=1)"
" Buffers: shared hit=3"
" -> Limit (cost=0.00..0.10 rows=1 width=233) (actual time=0.023..0.024 rows=1 loops=1)"
" Buffers: shared hit=1"
" -> CTE Scan on cl (cost=0.00..997.20 rows=9972 width=233) (actual time=0.021..0.021 rows=1 loops=1)"
" Buffers: shared hit=1"
" -> Limit (cost=10.00..10.10 rows=1 width=233) (actual time=0.117..0.118 rows=1 loops=1)"
" Buffers: shared hit=2"
" -> CTE Scan on cl cl_1 (cost=0.00..997.20 rows=9972 width=233) (actual time=0.001..0.104 rows=101 loops=1)"
" Buffers: shared hit=2"
"Planning Time: 0.634 ms"
"Execution Time: 0.248 ms"Aga lugeda plaani tekstina âpaberiltâ â on vĂ€ga keeruline ja raskesti mĂ”istetav:
- sÔlmes kuvatakse alamsÔlmede ressursside summa
ehk et mĂ”ista, kui palju aega kulus konkreetse sĂ”lme tĂ€itmiseks vĂ”i kui palju just see tabelist lugemine andmeid kettalt tĂ”i â tuleb kuidagi ĂŒks teisest vĂ€lja arvutada - sĂ”lme aeg on vajalik korrutada loops
jah, lahutamine ei ole veel kĂ”ige keerulisem tehe, mida tuleb «meeles» teha â sest tĂ€itmise aeg mÀÀratakse keskmisena ĂŒhe sĂ”lme tĂ€itmiseks, ja neid vĂ”ib olla sadu - noh, ja kĂ”ik see kokku takistab vastamast peamisele kĂŒsimusele â nii kes on siis «nĂ”rk lĂŒli»?
Kui me pĂŒĂŒdsime seda selgitada mitmele sajale meie arendajale, siis mĂ”istsime, et vĂ€ljastpoolt nĂ€eb see vĂ€lja umbes nii:

Ah, nii et meil on vajaâŠ
Tööriista
Sellesse oleme pĂŒĂŒdnud koguda kĂ”ik vĂ”tme mehhanismid, mis aitavad plaani ja pĂ€ringu kaudu mĂ”ista, «kes on sĂŒĂŒdi ja mida teha». Noh, ja jagada osa oma kogemustest kogukonnaga.
Tere tulemast ja kasutage â
Plaanide selgus
Kas on lihtne mÔista plaani, kui see vÀlja nÀeb nii?
Seq Scan on pg_class (reaalne aeg=0.009..1.304 read=6609 loops=1)
Buffers: jagatud hit=263
Planeerimise aeg: 0.108 ms
TĂ€itev aeg: 1.800 ms
Ei ole eriti.
Aga nii, lĂŒhendatud kujul, kui peamised nĂ€itajad on eraldatud â on juba palju selgem:

Aga kui plaan on veidi keerulisem â tuleb appi aegade jaotuse piechart sĂ”lmede jĂ€rgi:

Noh, ja kÔige keerulisemate variantide puhul kiirustab appi tÀitmise diagramm:

NĂ€iteks vĂ”ivad olla piisavalt keerulised olukorrad, kus plaanil vĂ”ib olla rohkem kui ĂŒks tegelik juur:


Struktuursed vihjed
Noh, ja kui kogu plaani struktuur ja selle nĂ”rgad kohad on juba vĂ€lja pandud ja nĂ€htavad â miks mitte tuua need arendajale esile ja selgitada "venekeeles"?
Selliseid soovitusmalle oleme kokku kogunud juba paar tosinat.
Reakutsiooni reaalajas profiiler
NĂŒĂŒd, kui analĂŒĂŒsitavale plaanile lisada algpĂ€rane pĂ€ring, siis on vĂ”imalik nĂ€ha, kui palju aega kulus iga konkreetse operaatori jaoks â umbes nii:

⊠vÔi isegi nii:

Parameetrite asendamine pÀringus
Kui olete "ĂŒhendanud" plaaniga mitte ainult pĂ€ringu, vaid ka selle parameetrid DETAIL-reast logis, siis saate kopeerida selle ka ĂŒhes variantidest:
- vÀÀrtuste asendamisega pÀringus
otse oma andmebaasis tÀitmiseks ja edasiseks profiilimiseksSELECT 'const', 'param'::text; - vÀÀrtuste asendamisega lÀbi PREPARE/EXECUTE
ajendaja töö emuleerimiseks, kui parameetriline osa vĂ”ib olla tĂ€helepanuta jĂ€etud â nĂ€iteks partitsioneeritud tabelite töötamiselDEALLOCATE ALL; PREPARE q(text) AS SELECT 'const', $1::text; EXECUTE q('param'::text);
Plaanide arhiiv
Sisestage, analĂŒĂŒsige, jagage kolleegidega! Plaanid jÀÀvad arhiivi ja saate hiljem nende juurde tagasi pöörduda:
Aga kui te ei soovi, et teie plaani teised nĂ€eksid, Ă€rge unustage mĂ€rkida vĂ€lja âĂ€rge avaldage arhiivisâ.
JĂ€rgmistes artiklites rÀÀgin keerukustest ja lahendustest, mis tekivad plaani analĂŒĂŒsimisel.
Allikas: habr.com
