A quistione classica chì un sviluppatore porta à u so DBA o un pruprietariu di l'impresa porta à un cunsultante PostgreSQL quasi sempre sona a stessa: "Perchè e dumande piglianu tantu tempu per cumpletà nantu à a basa di dati?"
Inseme tradiziunale di ragioni:
- algoritmu inefficace
quandu decide di unisce à parechji CTE nantu à un paru di decine di millaie di dischi - statistiche obsolete
se a distribuzione attuale di dati in a tavula hè digià assai sfarente da quella cullighjata da ANALYSE l'ultima volta - "plugging" in risorse
è ùn ci hè più una putenza di computazione dedicata di u CPU, gigabyte di memoria sò constantemente pompati, o u discu ùn pò micca seguità cù tutti i "voglia" di a basa di dati. - bluccamentu da i prucessi cuncurrenti
E se i blocchi sò abbastanza difficiuli di catturà è analizà, allora per tuttu ciò chì avemu bisognu pianu di dumanda, chì pò esse acquistatu usendu (Hè megliu, di sicuru, per spiegà subitu (ANALISI, BUFFERS) ...) o .
Mais, comme indiqué dans la même documentation,
"Capisce un pianu hè un arte, è per ammaistrà hè bisognu di una certa sperienza ..."
Ma pudete fà senza ellu sè vo aduprate u strumentu ghjustu!
Chì ghjè un pianu di dumanda tipicamente? Qualcosa cusì:
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=1o cusì:
"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"Ma leghje u pianu in u testu "da u fogliu" hè assai difficiule è pocu chjaru:
- hè visualizatu in u node somma da risorse subtree
vale à dì, per capisce quantu tempu hà pigliatu per eseguisce un nodu particulari, o quantu esattamente sta lettura da a tavula hà purtatu dati da u discu, avete bisognu di sottrae in qualchì modu unu da l'altru. - U tempu di u nodu hè necessariu multiplicate per loops
iè, a sottrazione ùn hè micca l'operazione più cumplessa chì deve esse fatta "in a testa" - dopu tuttu, u tempu d'esekzione hè indicatu cum'è a media per una esecuzione di un node, è ci ponu esse centinaie di elli. - bè, è tuttu questu inseme ci impedisce di risponde à a quistione principale - cusì chì "u ligame più debule"?
Quandu avemu pruvatu à spiegà tuttu questu à parechji cintunari di i nostri sviluppatori, avemu capitu chì da l'esternu pareva qualcosa cusì:

È questu significa chì avemu bisognu ...
Tool
In questu avemu pruvatu à cullà tutti i meccanichi chjave chì aiutanu à capiscenu "quale hè a culpa è ciò chì fà" secondu u pianu è a dumanda. Ebbè, è sparte una parte di a vostra sperienza cù a cumunità.
Incontra è aduprà -
Visibilità di i piani
Hè faciule per capisce u pianu quandu pare cusì?
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
Micca veramente.
Ma cusì, in forma abbreviataquandu l'indicatori chjave sò separati, hè assai più chjaru:

Ma s'è u pianu hè più cumplicatu, vinarà in salvezza Distribuzione di u tempu di piechart per nodi:

Ebbè, per l'opzioni più difficiuli, hè prestu per aiutà carta di prugressu:

Per esempiu, ci sò situazioni abbastanza micca triviali quandu un pianu pò avè più di una radica attuale:


Indicazioni strutturali
Ebbè, se tutta a struttura di u pianu è i so punti dolenti sò digià disposti è visibili, perchè ùn li mette in risaltu à u sviluppatore è spiegà in "lingua russa"?
Avemu digià recullatu un paru di decine di tali mudelli di raccomandazione.
Profilatore di dumande linea per linea
Avà, se superpone a quistione originale nantu à u pianu analizatu, pudete vede quantu tempu hè statu passatu per ogni dichjarazione individuale - qualcosa cum'è questu:

... o ancu cusì:

Sustituitu i paràmetri in una dumanda
Sè avete "attaccatu" micca solu una dumanda à u pianu, ma ancu i so parametri da a linea DETAIL di u logu, pudete ancu copià in una di l'opzioni:
- cù a sustituzione di valore in a dumanda
per l'esekzione diretta nantu à a vostra basa è più prufiluSELECT 'const', 'param'::text; - cù a sustituzione di valore via PREPARE/EXECUTE
per emulà u travagliu di u pianificatore, quandu a parte parametrica pò esse ignorata - per esempiu, quandu si travaglia nantu à tavule partizionateDEALLOCATE ALL; PREPARE q(text) AS SELECT 'const', $1::text; EXECUTE q('param'::text);
Archivio di piani
Incolla, analizà, sparte cù i culleghi ! I piani restanu archiviati è pudete vultà à elli dopu:
Ma sè ùn vulete micca chì l'altri vedanu u vostru pianu, ùn vi scurdate di verificà a casella "ùn pubblicà micca in archiviu".
In l'articuli seguenti, parraraghju di e difficultà è e decisioni chì nascenu quandu analizà un pianu.
Source: www.habr.com
