Paljud, kes juba kasutavad â meie PostgreSQL plaanide visualiseerimise teenust, ei pruugi olla teadlikud ĂŒhe tema supervĂ”ime â keerulisest serveri logi kĂ€rpimise teisendamisestâŠ

⊠ilusaks vormindatud pÀringuks kontekstuaalsete vihjetega vastavate plaanide sÔlmedele:

Selles oma rÀÀgin, kuidas me selle saavutame.
Esimese osa transkriptsiga, mis kĂ€sitleb tĂŒĂŒpilisi pĂ€ringute jĂ”udluse probleeme ja nende lahendusi, saate tutvuda artiklis .

Alustame vĂ€rvimisest â ja vĂ€rvime juba mitte plaani, see on meil juba ilus ja arusaadav, vaid pĂ€ringut.
Meie arvates nĂ€eb eksportimisse logidest vĂ€lja nĂ€htud âriidesâ vĂ€ga kole vĂ€lja ja seega â ebamugav.

Eriti kui arendajad âliimivadâ pĂ€ringu keha koodi (see on muidugi antipattern, kuid juhtub) ĂŒhte ritta. Kohutav!
Kujundame selle kuidagi ilusamaks.

Ja kui suudame selle ilusateks kujundada, siis saame pĂ€ringu iga objekti jaoks âpaigaldadaâ vihje â mis toimus vastavas plaanipunktis.
PĂ€ringu sĂŒntaktiline puu
Selleks tuleb pĂ€ring kĂ”igepealt analĂŒĂŒsida.

Kuna meil , siis tegime sellele mooduli, vĂ”ite . Tegelikult on see laiemad âsidumisedâ PostgreSQL-i parseri sisestruktuuride suhtes. See tĂ€hendab lihtsalt binaarselt koostatud grammatika ning sellele on tehtud sidumised NodeJS-i poolt. Kasutasime teiste moodulite baasi â siin pole suurt saladust.
Söötime pĂ€ringu keha meie funktsiooni sisendisse â vĂ€ljundina saame analĂŒĂŒsitud sĂŒntaktilise puu JSON-objekti kujul.

NĂŒĂŒd saab seda puu kaudu tagurpidi joosta ja koguda pĂ€ringu, mida soovime, mingite sisetĂ”mmete, vĂ€rvimise, vormindamisega. Ei, see ei ole konfigureeritav, kuid tundus, et just nii oleks mugav.

PÀringu ja plaani sÔlmede vastavus
NĂŒĂŒd vaatame, kuidas saame ĂŒhendada plaani, mille me esimeses etapis analĂŒĂŒsisime, ja pĂ€ringu, mille analĂŒĂŒsisime teises etapis.
VĂ”tame lihtsa nĂ€ite â meil on pĂ€ring, mis moodustab CTE ja loeb sellest kaks korda. See genereerib sellise plaani.

CTE
Kui sellele tÀhelepanelikult vaadata, siis kuni 12. versioonini (vÔi alates sellest, koos reaalsÔnaga MATERIALIZED) on loomine .

Seega, kui me nĂ€eme kusagil pĂ€ringus CTE genereerimist ja kusagil plaanis sĂ”lme CTE, siis need sĂ”lmed on kindlasti omavahel seotud, me saame need kohe ĂŒhendada.
Ălesanne 'tĂ€rniga': CTE-d vĂ”ivad olla pesakohtadest.

Need vÔivad olla vÀga halvasti pesakohtades, ja isegi sama nimega. NÀiteks vÔite sees CTE A moodi CTE X, ja samal tasemel sees CTE B teha jÀlle CTE X:
WITH A AS (
WITH X AS (...)
SELECT ...
)
, B AS (
WITH X AS (...)
SELECT ...
)
...Seda kokkupanekut peab mĂ”istma. MĂ”ista seda 'silmadega' â isegi nĂ€hes plaani, isegi nĂ€hes pĂ€ringu keha â on vĂ€ga raske. Kui teil on CTE genereerimine keeruline, pesakohtades, pĂ€ringud suured â siis pole see ĂŒldse aru saanud.
kogumi operaator, toetavad
Kui meie pĂ€ringus on reaalsĂ”na UNION [ALL] (kahe valiku ĂŒhendamise operaator), vastab sellele plaanis kas sĂ”lm Lisa, vĂ”i mĂ”ni Rekursiivne Liit.

See, mis 'ĂŒles' on meie sĂ”lme esimene laps, ja mis 'alla' â teine. Kui lĂ€bi kogumi operaator, toetavad meil on 'liimitud' mitu plokki korraga, siis kogumi operaator, toetavad -sĂ”lm on ainult ĂŒks, aga 'lapsesid' on tal mitte kaks, vaid palju â vastavalt nende jĂ€rjekonnale: Lisa(...) -- #1 UNION ALL (...) -- #2 UNION ALL (...) -- #3
Append
-> ... #1
-> ... #2
-> ... #3: sees genereerimise rekurssi valik (
Ălesanne 'tĂ€rniga') vĂ”ib samuti olla rohkem kui ĂŒks.WITH RECURSIVEKuid alati on rekursiivne ainult viimane plokk pĂ€rast viimast. kogumi operaator, toetavadKĂ”ik, mis ĂŒleval â see on ĂŒks, aga teine kogumi operaator, toetavadWITH RECURSIVE T AS( (...) -- #1 UNION ALL (...) -- #2, siin lĂ”peb rekursside algseisundi genereerimine UNION ALL (...) -- #3, ainult see plokk on rekursiivne ja vĂ”ib sisaldada viite T-le ) ... kogumi operaator, toetavad:
Taolisi nĂ€iteid peab samuti oskama 'lahutada'. Siin nĂ€eme, et -segmente meie pĂ€ringus oli 3 tĂŒkki. Seega, ĂŒhele kogumi operaator, toetavad-sĂ”lm, ja teisele â kogumi operaator, toetavad vastab LisaAndmete lugemine ja kirjutamine Rekursiivne Liit.

Nii, me oleme lahti harutanud, nĂŒĂŒd teame, milline tĂŒkk pĂ€ringust vastab millisele tĂŒkk plaanist. Ja nendes tĂŒkkides saame lihtsalt ja vaevata leida need objektid, mida 'loetakse'.
PĂ€ringu seisukohalt me ei tea â kas see on tabel vĂ”i CTE, kuid need tĂ€histatakse sama sĂ”lmega.
KĂŒsimuse vaatepunktist ei tea me, kas see on tabel vĂ”i CTE, kuid neid tĂ€histatakse sama sĂ”lmega. RangeVar. Ja plaan âloetavâ - see on samuti ĂŒsna piiratud sĂ”lmede kogum:
JĂ€rjesta skaneerimine [tbl] pealBitmapi virna skaneerimine [tbl] pealIndeks [Ainult] Skaneeri [Tagasi] kasutades [idx] [tbl] pealCTE skannimine [cte] pealSisestage/Uuenda/Kustutage [tbl] peal
Me teame plaani ja pĂ€ringu struktuuri, teame plokkide vastavust, teame objektide nimesid - teeme ĂŒhemĂ”ttelise vastavuse.

JĂ€llegi ĂŒlesanne âtĂ€hegaâ. VĂ”tame pĂ€ringu, tĂ€idame selle, meil ei ole mingeid alias'e - me lihtsalt lugesime kaks korda ĂŒhest CTE-st.

Vaata plaani - mis hĂ€da? Miks meil alias ilmus? Me ei tellinud seda. Kust see ânumbrilineâ tuli?
PostgreSQL lisab selle ise. Tuleb lihtsalt mĂ”ista, et selline alias ei oma meile plaaniga vastavuse eesmĂ€rkide jaoks mingit mĂ”tet, see on lihtsalt siin lisatud. Ărge pöörake sellele tĂ€helepanu.
Teine ĂŒlesanne âtĂ€hegaâ: kui meil on lugemine jaotatud tabelist, saame sĂ”lme Lisa vĂ”i Ăhenda Lisa, mis koosneb suurest hulgast âlastestâ, kellest igaĂŒks on mingi Scan'ist jaotustabelist: JĂ€rjesta skaneerimine, Bitmapi virna skaneerimine vĂ”i Index Scan. Kuid igal juhul ei ole need âlapsedâ keerulised pĂ€ringud - neid sĂ”lmi saab eristada Lisa kui kogumi operaator, toetavad.

Selliseid sĂ”lmi mĂ”istame ka, kogume âĂŒhte kuhjaâ ja ĂŒtleme: "kĂ”ik, mida sa lugesid megatable'ist - see on siin ja allpool puu".
âLihtsadâ andmete saamise sĂ”lmed

VÀÀrtuste skaneerimine plaanis vastab VĂĂRTUSTE pĂ€ringus.
Tulemus â see on pĂ€ring ilma KUST nĂ€iliselt SELECT 1. VĂ”i kui sul on vale vĂ€ljend KUS-plokis (siis tekib atribuut One-Time Filter):
EXPLAIN ANALYZE
SELECT * FROM pg_class WHERE FALSE; -- vĂ”i 0 = 1Tulemus (kulu=0.00..0.00 read=0 laius=230) (tode 0.000..0.000 read=0 tsĂŒklid=1)
One-Time Filter: false
Funktsiooni skanner âmaapuvadâ vastava SRF-ga.
Kuid sisemiste pÀringutega on kÔik keerulisem - kahjuks ei muutu need alati Algusplaan/Alusplaan. MÔnikord muutuvad nad ... Join vÔi ... Anti Join, eriti kui sa kirjutad midagi sarnast WHERE NOT EXISTS .... Ja seal kombineerimine ei pruugi alati Ônnestuda - plaani tekstis vastavaid sÔlme operaatoritest pole.
JĂ€llegi ĂŒlesanne âtĂ€hegaâ: mitu VĂĂRTUSTE pĂ€ringus. Sellisel juhul saad plaanis mitu sĂ”lme VÀÀrtuste skaneerimine.

Eristada neid ĂŒksteisest aitavad ânumbrilisedâ suffiksid - need lisatakse tĂ€pselt plokkide vastavuse leidmise jĂ€rjekorras pĂ€ringu ĂŒlemisest osast alla. VĂĂRTUSTEAndmete töötlemine
Tundub, et oleme oma pÀringus kÔik lahti seletanud - alles on jÀÀnud vaid
Aga siin on kÔik lihtne - sellised sÔlmed nagu Piirang.

âmaapuvadâ ĂŒks-ĂŒhele vastavatele operaatoritele pĂ€ringus, kui need seal olemas on. Siin ei ole mingeid âtĂ€hekesedâ ega raskusi. Piirang, Sorteeri, Kogumine, WindowAgg, Ainulaadne Raskused tekivad, kui me tahame ĂŒhendada

JOIN
oma vahel. Seda ei ole alati lihtne teha, kuid vÔimalik. JOIN oma vahel. Seda ei ole alati vÔimalik teha, kuid see on vÔimalik.

KĂŒsimuse parsija seisukohalt on meil sĂ”lm, LiituExpr, millel on tĂ€pselt kaks last â vasak ja parem. See on vastavalt see, mis on teie JOIN âĂŒlevalâ ja see, mis on âallâ kirjutatud.
Ja plaani seisukohalt on see kaks last mĂ”nest * TsĂŒkkel/* Liitu-sĂ”lmest. SisekĂ€ik, Hash Anti Join,⊠â midagi sellist.
Kasutame lihtsat loogikat: kui meil on tabelid A ja B, mis âliituvadâ omavahel plaanis, siis vĂ”isid nad pĂ€ringus olla paigutatud kas A-JOIN-B, vĂ”i B-JOIN-A. Proovime neid nii ĂŒhendada, proovime ĂŒhendada vastupidiselt, ja nii kaua kuni sellised paarid otsa saavad.
VĂ”tame meie sĂŒntaktilise puu, vĂ”tame meie plaani, vaatame neid⊠ei sarnane!

Joonistame uuesti graafide vormis â o, nĂŒĂŒd hakkab midagi sarnast olema!

Pöörame tĂ€helepanu, et meil on sĂ”lmed, millel on samal ajal lapsed B ja C â meile ei ole oluline, mis jĂ€rjekorras. Ăhendame need ja pöörame sĂ”lme pildi ĂŒmber.

Vaadakem veel kord. NĂŒĂŒd on meil sĂ”lmed lastega A ja paar (B + C) â ĂŒhendame ka need.

Fantastiline! Tundub, et me oleme need kaks JOIN pÀringust plaani sÔlmedega edukalt kokku viinud.
Kahjuks ei lahene see ĂŒlesanne alati.

NĂ€iteks, kui pĂ€ringus on A JOIN B JOIN C, aga plaanis liitusid alguses âÀÀrmuslikudâ sĂ”lmed A ja C. Ja pĂ€ringus pole sellist operaatorit, meil pole midagi, mida esile tĂ”sta, pole millele vihjet siduda. Sama kehtib âkommaâ kohta, kui kirjutate A, B.
Kuid enamikul juhtudel Ă”nnestub peaaegu kĂ”ik sĂ”lmed âlahti sidudaâ ja saada midagi sellist profiileerimise jĂ€rgi vasakul ajale â literally, nagu Google Chrome'is, kui analĂŒĂŒsite JavaScripti koodi. NĂ€ete, kui palju aega iga rida ja iga operaator âtĂ€idetiâ.

Ja et teil oleks kÔigega mugavam kasutada, oleme loonud salvestuse , kus saate salvestada ja hiljem leida oma plaane koos seotud pÀringutega vÔi kellegagi jagada linki.
Kui teil on lihtsalt vaja tuua lugematu pÀring korrektsetesse vormidesse, kasutage .

Allikas: habr.com
