Klassíska spurningin sem verktaki kemur með til DBA eða fyrirtækjaeigandi kemur með til PostgreSQL ráðgjafa hljómar næstum alltaf eins: "Hvers vegna taka beiðnir svona langan tíma að klára í gagnagrunninum?"
Hefðbundnar ástæður:
- óhagkvæmt reiknirit
þegar þú ákveður að TENGLA MEÐ nokkrum CTEs á nokkrum tugþúsundum skráa - úrelt tölfræði
ef raunveruleg dreifing gagna í töflunni er þegar mjög frábrugðin þeirri sem ANALYZE safnaði síðast - „tengdu“ auðlindir
og það er ekki lengur nóg hollt tölvuafl örgjörvans, gígabætum af minni er stöðugt verið að dæla eða diskurinn getur ekki fylgst með öllum „óskum“ gagnagrunnsins - lokun frá samkeppnisferlum
Og ef það er frekar erfitt að grípa og greina blokkanir, þá fyrir allt annað sem við þurfum fyrirspurnaráætlun, sem hægt er að fá með því að nota
En eins og fram kemur í sömu skjölum,
„Að skilja áætlun er list og til að ná tökum á henni þarf ákveðna reynslu...“
En þú getur verið án þess ef þú notar rétt tól!
Hvernig lítur fyrirspurnaáætlun venjulega út? Eitthvað svoleiðis:
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=1
eða svona:
"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"
En að lesa áætlunina í texta „af blaðinu“ er mjög erfitt og óljóst:
- birtist í hnútnum summa eftir auðlindum undirtrés
það er, til að skilja hversu mikinn tíma það tók að keyra tiltekinn hnút, eða hversu mikið nákvæmlega þessi lestur úr töflunni leiddi til gagna af disknum, þarftu einhvern veginn að draga einn frá öðrum - hnútatíma þarf margfalda með lykkjum
já, frádráttur er ekki flóknasta aðgerðin sem þarf að gera „í hausnum“ - þegar allt kemur til alls er framkvæmdartíminn gefinn upp sem meðaltal fyrir eina framkvæmd á hnút og þeir geta verið hundruðir - jæja, og allt þetta saman kemur í veg fyrir að við getum svarað aðalspurningunni - svo hver "veikasti hlekkurinn"?
Þegar við reyndum að útskýra þetta allt fyrir nokkrum hundruðum hönnuða okkar, áttuðum við okkur á því að utan frá leit þetta einhvern veginn svona út:
Og það þýðir að við þurfum...
Tól
Í henni reyndum við að safna öllum helstu vélvirkjum sem hjálpa til við að skilja „hverjum er um að kenna og hvað á að gera“ samkvæmt áætluninni og beiðninni. Jæja, og deildu hluta af reynslu þinni með samfélaginu.
Hittu og notaðu -
Sýnileiki áætlana
Er auðvelt að skilja áætlunina þegar hún lítur svona út?
Seq Scan on pg_class (actual time=0.009..1.304 rows=6609 loops=1)
Buffers: shared hit=263
Planning Time: 0.108 ms
Execution Time: 1.800 ms
Ekki í raun.
En svona, í styttri myndþegar lykilvísarnir eru aðskildir er það miklu skýrara:
En ef áætlunin er flóknari kemur hann til bjargar piechart tímadreifingu eftir hnútum:
Jæja, fyrir erfiðustu valkostina er hann að flýta sér að hjálpa framvindurit:
Til dæmis eru alveg óléttar aðstæður þegar áætlun getur haft fleiri en eina raunverulega rót:
Skipulagslegar vísbendingar
Jæja, ef öll uppbygging áætlunarinnar og sársauka blettir hennar eru þegar settir út og sýnilegir, hvers vegna ekki að auðkenna þau fyrir framkvæmdaraðila og útskýra þau á „rússnesku“?
Við höfum þegar safnað nokkrum tugum slíkra meðmælasniðmáta.
Fyrirspurnarsniður fyrir línu fyrir línu
Nú, ef þú setur upprunalegu fyrirspurnina ofan á greindu áætlunina, geturðu séð hversu miklum tíma var eytt í hverja einstaka yfirlýsingu - eitthvað á þessa leið:
...eða jafnvel svona:
Að skipta breytum út í beiðni
Ef þú „hengdir“ ekki aðeins beiðni við áætlunina, heldur einnig færibreytur hennar úr DETAIL línunni í skránni, geturðu að auki afritað hana í einum af valkostunum:
- með gildisskiptum í beiðninni
fyrir beina framkvæmd á stöðinni þinni og frekari prófílgreininguSELECT 'const', 'param'::text;
- með gildisskiptum í gegnum PREPARE/EXECUTE
til að líkja eftir vinnu tímaáætlunaraðilans, þegar hægt er að hunsa færibreytuhlutann - til dæmis þegar unnið er á skiptingartöflumDEALLOCATE ALL; PREPARE q(text) AS SELECT 'const', $1::text; EXECUTE q('param'::text);
Skjalasafn áætlana
Límdu, greindu, deildu með samstarfsfólki! Áætlanirnar verða áfram í geymslu og þú getur farið aftur í þær síðar:
En ef þú vilt ekki að aðrir sjái áætlunina þína, ekki gleyma að haka við „ekki birta í skjalasafni“ reitinn.
Í eftirfarandi greinum mun ég tala um erfiðleika og ákvarðanir sem koma upp þegar áætlun er greind.
Heimild: www.habr.com