PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Multaj kiuj jam uzas klarigi.tensor.ru - nia PostgreSQL-plana bildiservo eble ne konscias pri unu el ĝiaj superpotencoj - por turni malfacile legeblan pecon de la servila protokolo ...

PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton
… en bele desegnitan demandon kun kontekstaj sugestoj por la koncernaj plannodoj:

PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton
En ĉi tiu transskribo de la dua parto de lia raporto ĉe PGConf.Russia 2020 Mi rakontos al vi kiel ni sukcesis fari ĝin.

La transskribo de la unua parto, dediĉita al tipaj demandaj agado-problemoj kaj iliaj solvoj, troveblas en la artikolo "Receptoj por Malsanaj SQL-Demandoj".



Unue, ni faru la kolorigon — kaj ni ne plu kolorigos la planon, ni jam pentris ĝin, ĝi jam estas bela kaj komprenebla, sed la peto.

Ŝajnis al ni, ke la peto eltirita el la ŝtipo kun neformata "folio" aspektas tre malbela kaj tial maloportuna.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Precipe kiam programistoj "gluas" la peton en la kodo (ĉi tio, kompreneble, estas kontraŭ-ŝablono, sed okazas) en unu linio. Teruro!

Ni desegnu ĝin iel pli bele.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Kaj se ni povas desegni ĝin bele, tio estas, malmunti kaj kunmeti la petan korpon reen, tiam ni povas "almeti" aludon al ĉiu objekto de ĉi tiu peto - kio okazis ĉe la responda punkto en la plano.

Demandu Sintakso-Arbon

Por fari tion, la demando unue devas esti analizita.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Ĉar, ni havas la kerno de la sistemo funkcias per NodeJS, tiam ni faris modulon por ĝi, vi povas trovi ĝin sur github. Fakte, ĉi tiuj estas etenditaj "ligoj" al la internoj de la PostgreSQL-analizilo mem. Tio estas, la gramatiko estas simple duuma kompilita kaj ligadoj estas faritaj al ĝi per NodeJS. Ni prenis aliulajn modulojn kiel bazon - ĉi tie ne estas granda sekreto.

Ni nutras la korpon de la eniga peto al nia funkcio - ĉe la eligo ni ricevas analizitan sintaksan arbon en formo de JSON-objekto.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Nun ni povas trakuri ĉi tiun arbon en la kontraŭa direkto kaj kunmeti la peton kun la indentaĵoj, kolorigo, formatado, kiujn ni volas. Ne, ĉi tio ne estas agordebla, sed ni pensis, ke tio estus oportuna.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Mapado de Demando kaj Planaj Nodoj

Nun ni vidu kiel ni povas kombini la planon, kiun ni analizis en la unua paŝo kaj la demandon, kiun ni analizis en la dua.

Ni prenu simplan ekzemplon - ni havas peton, kiu formas CTE kaj legas ĝin dufoje. Li generas tian planon.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

CTE

Se vi rigardas ĝin atente, tio antaŭ la 12-a versio (aŭ komencante de ĝi per la ŝlosilvorto MATERIALIZED) formado CTE estas senkondiĉa baro al la planisto.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Kaj tio signifas, se ni vidas ie en la peto la generacion de CTE kaj ie en la plano la nodon CTE, tiam ĉi tiuj nodoj unike "batalas" inter si, ni povas tuj kombini ilin.

Tasko "kun asterisko"Notu: CTE-oj povas esti nestitaj.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton
Estas tre malbone nestitaj, kaj eĉ samnomaj. Ekzemple, vi povas interne CTE A fari CTE X, kaj samnivele interne CTE B faru denove CTE X:

WITH A AS (
  WITH X AS (...)
  SELECT ...
)
, B AS (
  WITH X AS (...)
  SELECT ...
)
...

Komparante, vi devas kompreni ĉi tion. Estas tre malfacile kompreni tion per "okuloj" - eĉ vidante la planon, eĉ vidante la korpon de la peto. Se via CTE-generacio estas kompleksa, nestita, la petoj estas grandaj, tiam ĝi estas tute senkonscia.

UNION

Se ni havas ŝlosilvorton en la peto UNION [ALL] (la operatoro de kunigado de du specimenoj), tiam ĝi respondas en la plano al aŭ la nodo Append, aŭ iuj Recursive Union.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Tio, kio estas "supre" UNION - ĉi tiu estas la unua infano de nia nodo, kiu estas "de malsupre" - la dua. Se tra UNION ni do "gluis" plurajn blokojn samtempe Append-node havos ankoraŭ nur unu, sed ĝi havos ne du infanojn, sed multajn - laŭ la ordo, respektive:

  (...) -- #1
UNION ALL
  (...) -- #2
UNION ALL
  (...) -- #3

Append
  -> ... #1
  -> ... #2
  -> ... #3

Tasko "kun asterisko": ene de rekursiva alporta generacio (WITH RECURSIVE) ankaŭ povas esti pli ol unu UNION. Sed nur la plej lasta bloko post la lasta estas ĉiam rekursiva UNION. Ĉio supre estas unu sed malsama UNION:

WITH RECURSIVE T AS(
  (...) -- #1
UNION ALL
  (...) -- #2, тут кончается генерация стартового состояния рекурсии
UNION ALL
  (...) -- #3, только этот блок рекурсивный и может содержать обращение к T
)
...

Tiaj ekzemploj ankaŭ bezonas povi "alglui". En ĉi tiu ekzemplo, ni vidas tion UNION-segmentoj en nia peto estis 3 pecoj. Sekve, unu UNION соответствует Append-nodo, kaj la alia - Recursive Union.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Legu-skribi datumojn

Ĉio, aranĝita, nun ni scias, kiu peco de la peto respondas al kiu peco de la plano. Kaj en ĉi tiuj pecoj ni povas facile kaj nature trovi tiujn objektojn, kiuj estas "legeblaj".

El la vidpunkto de la konsulto, ni ne scias ĉu ĉi tio estas tabelo aŭ CTE, sed ili estas indikitaj per la sama nodo. RangeVar. Kaj en la "legebla" plano, ĉi tio ankaŭ estas sufiĉe limigita aro de nodoj:

  • Seq Scan on [tbl]
  • Bitmap Heap Scan on [tbl]
  • Index [Only] Scan [Backward] using [idx] on [tbl]
  • CTE Scan on [cte]
  • Insert/Update/Delete on [tbl]

Ni konas la strukturon de la plano kaj la peto, ni konas la korespondadon de la blokoj, ni konas la nomojn de la objektoj - ni faras senduban komparon.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Denove tasko "kun asterisko". Ni prenas peton, plenumas ĝin, ni ne havas kaŝnomojn - ni nur legas ĝin dufoje de unu CTE.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Ni rigardu la planon - kio estas la problemo? Kial ni havis kaŝnomon? Ni ne mendis ĝin. De kie li ricevas tian "nombron"?

PostgreSQL aldonas ĝin mem. Vi nur bezonas kompreni tion ĝuste tia kaŝnomo por ni, por komparo kun la plano, ĝi ne havas sencon, ĝi estas simple aldonita ĉi tie. Ni ne atentu lin.

La dua tasko "kun asterisko": se ni legas el dividita tablo, tiam ni ricevos nodon AppendMerge Append, kiu konsistos el granda nombro da "infanoj", kaj ĉiu el kiuj estos kelkaj Scan'om de la tablo-sekcio: Seq Scan, Bitmap Heap ScanIndex Scan. Sed, ĉiukaze, ĉi tiuj "infanoj" ne estos kompleksaj demandoj - jen kiel ĉi tiuj nodoj povas esti distingitaj de Append ĉe UNION.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Ni ankaŭ komprenas tiajn nodojn, ni kolektas ilin "en unu amaso" kaj diras: "ĉio, kion vi legas de megatable, estas ĝuste ĉi tie kaj sub la arbo".

"Simplaj" Datumaj Akiro-Nodoj

PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Values Scan en plano respondas VALUES en la peto.

Result estas peto sen FROM Ŝati SELECT 1. Aŭ kiam vi havas malveran esprimon en WHERE-bloko (tiam aperas la atributo One-Time Filter):

EXPLAIN ANALYZE
SELECT * FROM pg_class WHERE FALSE; -- или 0 = 1

Result  (cost=0.00..0.00 rows=0 width=230) (actual time=0.000..0.000 rows=0 loops=1)
  One-Time Filter: false

Function Scan "Mapyatsya" sur la SRF de la sama nomo.

Sed kun nestitaj demandoj, ĉio estas pli komplika - bedaŭrinde, ili ne ĉiam iĝas InitPlan/SubPlan. Foje ili iĝas ... Join... Anti Join, precipe kiam vi skribas ion tian WHERE NOT EXISTS .... Kaj ne ĉiam eblas kombini tie - en la teksto de la plano ne ekzistas operatoroj respondaj al la nodoj de la plano.

Denove tasko "kun asterisko": iuj VALUES en la peto. En ĉi tiu kazo kaj en la plano vi ricevos plurajn nodojn Values Scan.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

"Nombro" sufiksoj helpos distingi ilin unu de la alia - ĝi estas aldonita ĝuste en la ordo en kiu la responda VALUES-blokoj dum la peto de supre malsupre.

Datumtraktado

Ŝajnas, ke ĉio en nia peto estis ordigita - nur Limit.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Sed ĉio estas simpla ĉi tie - tiaj nodoj kiel Limit, Sort, Aggregate, WindowAgg, Unique Ili "mapas" unu-al-unu al la respondaj operatoroj en la peto, se ili estas tie. Ne estas "steloj" kaj neniuj malfacilaĵoj.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

JOIN

Malfacilaĵoj aperas kiam ni volas kombini JOIN inter si. Ĉi tio ne ĉiam eblas, sed ĝi eblas.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

El la vidpunkto de la demanda analizisto, ni havas nodon JoinExpr, kiu havas ekzakte du infanojn - maldekstren kaj dekstren. Ĉi tio, respektive, estas kio estas "super" via JOIN kaj kio estas skribita "sub" en la demando.

Kaj el la vidpunkto de la plano, ĉi tiuj estas du posteuloj de iuj * Loop/* Join-nodo. Nested Loop, Hash Anti Join... estas io tia.

Ni uzu simplan logikon: se ni havas tabelojn A kaj B kiuj "kuniĝas" unu la alian en la plano, tiam en la konsulto ili povus troviĝi ĉu A-JOIN-BB-JOIN-A. Ni provu kombini tiel, provu kombini en la kontraŭa maniero, kaj tiel plu ĝis elĉerpiĝos tiaj paroj.

Prenu nian sintaksarbon, prenu nian planon, rigardu ilin... ĝi ne aspektas kiel ĝi!
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Ni redesegnu ĝin en formo de grafikaĵoj - ho, io jam fariĝis simila al io!
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Ni rimarku, ke ni havas nodojn, kiuj havas filojn B kaj C samtempe - al ni ne gravas en kiu ordo. Ni kombinu ilin kaj renversu la bildon de la nodo.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Ni rigardu denove. Nun ni havas nodojn kun infanoj A kaj paroj (B + C) - kongruaj kun ili.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Bonege! Montriĝas, ke ni estas ĉi tiuj du JOIN de la konsulto kun la nodoj de la plano estis sukcese kombinitaj.

Ve, ĉi tiu problemo ne ĉiam estas solvita.
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Ekzemple, se la peto A JOIN B JOIN C, kaj en la plano, la "ekstremaj" nodoj A kaj C estis ligitaj antaŭ ĉio. Sed ne ekzistas tia operatoro en la konsulto, ni havas nenion por reliefigi, estas nenio por ligi la sugeston. Same kun "komo" kiam vi skribas A, B.

Sed, plejofte, preskaŭ ĉiuj nodoj sukcesas "malligi" kaj akiri tian profiladon maldekstre ĝustatempe - laŭvorte, kiel en Google Chrome, kiam vi analizas JavaScript-kodon. Vi povas vidi kiom longe ĉiu linio kaj ĉiu deklaro "ekzekutita".
PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

Kaj por faciligi al vi uzi ĉion ĉi, ni faris stokadon la arĥivo, kie vi povas konservi kaj poste trovi viajn planojn kune kun rilataj demandoj aŭ dividi ligon kun iu.

Se vi nur bezonas alporti nelegeblan peton en taŭgan formon, uzu nia "normaligilo".

PostgreSQL Query Profiler: Kiel kongrui planon kaj konsulton

fonto: www.habr.com

Aldoni komenton