ProHoster > blog > Utawala > Profaili ya Swali la PostgreSQL: jinsi ya kulinganisha mpango na hoja
Profaili ya Swali la PostgreSQL: jinsi ya kulinganisha mpango na hoja
Wengi ambao tayari wanatumia eleza.tensor.ru - Huduma yetu ya utazamaji wa mpango wa PostgreSQL inaweza kuwa haifahamu mojawapo ya nguvu zake kuu - kubadilisha kipande cha kumbukumbu cha seva ambacho ni kigumu kusomeka...
... katika swali lililoundwa kwa uzuri na vidokezo vya muktadha kwa nodi za mpango zinazolingana:
Nakala ya sehemu ya kwanza, iliyowekwa kwa shida za kawaida za utendakazi wa hoja na suluhisho zao, inaweza kupatikana katika kifungu. "Maelekezo ya maswali ya SQL mgonjwa".
Kwanza, hebu tuanze kuchorea - na hatuwezi tena rangi ya mpango, tayari tumepiga rangi, tayari tunayo nzuri na inayoeleweka, lakini ombi.
Ilionekana kwetu kuwa kwa "karatasi" isiyo na muundo kama huo ombi lililotolewa kutoka kwa logi inaonekana kuwa mbaya sana na kwa hivyo haifai.
Hasa wakati watengenezaji "gundi" mwili wa ombi katika kanuni (hii ni, bila shaka, antipattern, lakini hutokea) katika mstari mmoja. Ya kutisha!
Wacha tuchore hii kwa uzuri zaidi.
Na ikiwa tunaweza kuchora hii kwa uzuri, ambayo ni, kutenganisha na kuweka pamoja mwili wa ombi, basi tunaweza "kuambatisha" wazo kwa kila kitu cha ombi hili - kile kilichotokea katika hatua inayolingana ya mpango.
Swali la mti wa syntax
Ili kufanya hivyo, ombi lazima kwanza lichanganuliwe.
Kwa sababu tuna msingi wa mfumo unaendesha NodeJS, kisha tukaitengenezea moduli, unaweza pata kwenye GitHub. Kwa kweli, hizi ni "vifungo" vilivyopanuliwa kwa watu wa ndani wa kichanganuzi cha PostgreSQL chenyewe. Hiyo ni, sarufi imeundwa kwa njia ya binary na vifungo vinafanywa kutoka kwa NodeJS. Tulichukua moduli za watu wengine kama msingi - hakuna siri kubwa hapa.
Tunalisha mwili wa ombi kama ingizo la utendakazi wetu - kwa matokeo tunapata mti wa sintaksia uliochanganuliwa katika mfumo wa kitu cha JSON.
Sasa tunaweza kukimbia kupitia mti huu katika mwelekeo tofauti na kukusanya ombi na indents, rangi, na umbizo tunataka. Hapana, hii haiwezi kubinafsishwa, lakini ilionekana kwetu kuwa hii itakuwa rahisi.
Hoja ya ramani na nodi za kupanga
Sasa hebu tuone jinsi tunavyoweza kuchanganya mpango ambao tulichanganua katika hatua ya kwanza na swali ambalo tulichambua katika pili.
Hebu tuchukue mfano rahisi - tuna swali ambalo hutoa CTE na kusoma kutoka humo mara mbili. Anatengeneza mpango kama huo.
Hii ina maana kwamba ikiwa tunaona kizazi cha CTE mahali fulani katika ombi na node mahali fulani katika mpango CTE, basi nodi hizi hakika "hupigana" na kila mmoja, tunaweza kuzichanganya mara moja.
Tatizo na nyota: CTE zinaweza kuwekwa.
Kuna viota duni sana, na hata vya majina sawa. Kwa mfano, unaweza ndani CTE A fanya CTE X, na kwa kiwango sawa ndani CTE B fanya tena CTE X:
WITH A AS (
WITH X AS (...)
SELECT ...
)
, B AS (
WITH X AS (...)
SELECT ...
)
...
Wakati wa kulinganisha, lazima uelewe hili. Kuelewa hii "kwa macho yako" - hata kuona mpango, hata kuona mwili wa ombi - ni ngumu sana. Ikiwa kizazi chako cha CTE ni ngumu, kimewekwa, na maombi ni makubwa, basi ni fahamu kabisa.
UNION
Ikiwa tunayo neno kuu katika swali UNION [ALL] (opereta wa kuunganisha sampuli mbili), basi katika mpango huo inafanana na node ama Append, au baadhi Recursive Union.
Ile "juu" hapo juu UNION - huyu ndiye mzao wa kwanza wa nodi yetu, ambayo iko "chini" - ya pili. Ikiwa kupitia UNION tuna vitalu kadhaa "glued" mara moja, basi Append-Bado kutakuwa na nodi moja tu, lakini haitakuwa na mbili, lakini watoto wengi - kwa mpangilio wanaoenda, mtawaliwa:
(...) -- #1
UNION ALL
(...) -- #2
UNION ALL
(...) -- #3
Append
-> ... #1
-> ... #2
-> ... #3
Tatizo na nyota: ndani ya kizazi cha sampuli inayojirudia (WITH RECURSIVE) pia inaweza kuwa zaidi ya moja UNION. Lakini kizuizi cha mwisho tu baada ya cha mwisho huwa kinajirudia kila wakati UNION. Kila kitu hapo juu ni moja, lakini tofauti UNION:
WITH RECURSIVE T AS(
(...) -- #1
UNION ALL
(...) -- #2, ΡΡΡ ΠΊΠΎΠ½ΡΠ°Π΅ΡΡΡ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΡ ΡΡΠ°ΡΡΠΎΠ²ΠΎΠ³ΠΎ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ ΡΠ΅ΠΊΡΡΡΠΈΠΈ
UNION ALL
(...) -- #3, ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠΎΡ Π±Π»ΠΎΠΊ ΡΠ΅ΠΊΡΡΡΠΈΠ²Π½ΡΠΉ ΠΈ ΠΌΠΎΠΆΠ΅Ρ ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΡ ΠΎΠ±ΡΠ°ΡΠ΅Π½ΠΈΠ΅ ΠΊ T
)
...
Pia unahitaji kuwa na uwezo wa "kuweka" mifano kama hiyo. Katika mfano huu tunaona hivyo UNION-kulikuwa na sehemu 3 katika ombi letu. Ipasavyo, moja UNION inafanana na Append-nodi, na kwa nyingine - Recursive Union.
Data ya kusoma-kuandika
Kila kitu kimewekwa, sasa tunajua ni kipande gani cha ombi kinacholingana na kipande gani cha mpango. Na katika vipande hivi tunaweza kupata kwa urahisi na kwa kawaida vitu hivyo ambavyo "vinasomeka".
Kwa mtazamo wa hoja, hatujui ikiwa ni jedwali au CTE, lakini zimeteuliwa kwa nodi sawa. RangeVar. Na kwa suala la "kusoma", hii pia ni seti ndogo ya nodi:
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]
Tunajua muundo wa mpango na swala, tunajua mawasiliano ya vitalu, tunajua majina ya vitu - tunafanya kulinganisha moja hadi moja.
Tena kazi "na nyota". Tunachukua ombi, kutekeleza, hatuna lakabu yoyote - tunaisoma mara mbili kutoka kwa CTE ile ile.
Tunaangalia mpango - shida ni nini? Kwa nini tulikuwa na alias? Hatukuiagiza. Anapata wapi "nambari" kama hiyo?
PostgreSQL inaongeza yenyewe. Unahitaji tu kuelewa hilo jina la utani kama hilo kwa ajili yetu, kwa madhumuni ya kulinganisha na mpango, haina maana yoyote, ni aliongeza tu hapa. Tusiwe makini naye.
Ya pili kazi "na nyota": ikiwa tunasoma kutoka kwa meza iliyogawanyika, basi tutapata node Append au Merge Append, ambayo itakuwa na idadi kubwa ya "watoto", na kila moja ambayo itakuwa kwa namna fulani Scan'om kutoka kwa sehemu ya jedwali: Seq Scan, Bitmap Heap Scan au Index Scan. Lakini, kwa hali yoyote, "watoto" hawa hawatakuwa maswali magumu - hivi ndivyo nodi hizi zinaweza kutofautishwa kutoka. Append saa UNION.
Pia tunaelewa mafundo kama haya, tunayakusanya "katika rundo moja" na kusema: "kila kitu unachosoma kutoka kwa megatable kiko hapa na chini ya mti".
"Rahisi" data kupokea nodi
Values Scan inalingana katika mpango VALUES katika ombi.
Result ni ombi bila FROM aina ya SELECT 1. Au unapokuwa na usemi wa uwongo kimakusudi WHERE-block (basi sifa inaonekana One-Time Filter):
EXPLAIN ANALYZE
SELECT * FROM pg_class WHERE FALSE; -- ΠΈΠ»ΠΈ 0 = 1
Lakini kwa maswali yaliyowekwa kiota kila kitu ni ngumu zaidi - kwa bahati mbaya, hazigeuki kila wakati InitPlan/SubPlan. Wakati mwingine hugeuka kuwa ... Join au ... Anti Join, hasa unapoandika kitu kama WHERE NOT EXISTS .... Na hapa si mara zote inawezekana kuchanganya nao - katika maandishi ya mpango hakuna waendeshaji sambamba na nodes za mpango.
Tena kazi "na nyota": baadhi VALUES katika ombi. Katika kesi hii na katika mpango utapata nodes kadhaa Values Scan.
Viambishi vya "Hesabu" vitasaidia kutofautisha kutoka kwa kila mmoja - huongezwa haswa kwa mpangilio ambao sawa hupatikana. VALUES-vizuizi pamoja na ombi kutoka juu hadi chini.
Usindikaji wa data
Inaonekana kila kitu katika ombi letu kimetatuliwa - kilichosalia ni Limit.
Lakini hapa kila kitu ni rahisi - nodi kama vile Limit, Sort, Aggregate, WindowAgg, Unique "ramani" moja kwa moja kwa waendeshaji sambamba katika ombi, ikiwa wapo. Hakuna "nyota" au shida hapa.
JOIN
Ugumu hutokea tunapotaka kuchanganya JOIN kati yao wenyewe. Hii haiwezekani kila wakati, lakini inawezekana.
Kwa mtazamo wa mchanganuzi wa hoja, tunayo nodi JoinExpr, ambayo ina watoto wawili hasa - kushoto na kulia. Hiki, ipasavyo, ndicho kilicho "juu" ya KUJIUNGA kwako na kile kilichoandikwa "chini" yake katika ombi.
Na kwa mtazamo wa mpango, hawa ni wazao wawili wa baadhi * Loop/* Join-nodi. Nested Loop, Hash Anti Join,... - kitu kama hicho.
Wacha tutumie mantiki rahisi: ikiwa tuna meza A na B ambazo "zinajiunga" katika mpango, basi katika ombi zinaweza kupatikana ama. A-JOIN-BAu B-JOIN-A. Hebu jaribu kuchanganya kwa njia hii, hebu tujaribu kuchanganya njia nyingine kote, na kadhalika mpaka tutakapokwisha jozi hizo.
Wacha tuichore tena kwa namna ya grafu - oh, tayari inaonekana kama kitu!
Hebu tukumbuke kwamba tuna nodes ambazo wakati huo huo zina watoto B na C - hatujali kwa utaratibu gani. Wacha tuwachanganye na tugeuze picha ya nodi.
Hebu tuangalie tena. Sasa tuna nodi na watoto A na jozi (B + C) - zinazoendana nao pia.
Kubwa! Inageuka kuwa sisi ni hawa wawili JOIN kutoka kwa ombi na nodi za mpango ziliunganishwa kwa mafanikio.
Ole, tatizo hili si mara zote kutatuliwa.
Kwa mfano, ikiwa katika ombi A JOIN B JOIN C, na katika mpango huo, kwanza kabisa, nodes za "nje" A na C ziliunganishwa. Lakini hakuna operator vile katika ombi, hatuna chochote cha kuonyesha, hakuna kitu cha kuunganisha kidokezo. Ni sawa na "comma" unapoandika A, B.
Lakini, katika hali nyingi, karibu nodi zote zinaweza "kufunguliwa" na unaweza kupata aina hii ya wasifu upande wa kushoto kwa wakati - kihalisi, kama kwenye Google Chrome unapochambua msimbo wa JavaScript. Unaweza kuona ni muda gani kila mstari na kila taarifa ilichukua "kutekeleza."
Na ili iwe rahisi kwako kutumia haya yote, tumehifadhi kumbukumbu, ambapo unaweza kuhifadhi na baadaye kupata mipango yako pamoja na maombi yanayohusiana au kushiriki kiungo na mtu fulani.
Ikiwa unahitaji tu kuleta swali lisiloweza kusoma katika fomu ya kutosha, tumia "kawaida" wetu.