Ngenxa yomgca wam womsebenzi, kufuneka ndijongane neemeko xa umphuhlisi ebhala isicelo kwaye acinge "Isiseko sihlakaniphile, siyakwazi ukusingatha yonke into ngokwayo!Β«
Kwezinye iimeko (inxalenye yokungazi kakuhle izakhono zesiseko sedatha, ngokuyinxenye ukusuka ekuphuculweni kwangaphambi kwexesha), le ndlela ikhokelela ekubonakaleni kwe "Frankensteins".
Okokuqala, ndiza kunika umzekelo wesicelo esinjalo:
-- Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠ»ΡΡΠ΅Π²ΠΎΠΉ ΠΏΠ°ΡΡ Π½Π°Ρ
ΠΎΠ΄ΠΈΠΌ Π°ΡΡΠΎΡΠΈΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠΎΠ»Π΅ΠΉ
WITH RECURSIVE cte_bind AS (
SELECT DISTINCT ON (key_a, key_b)
key_a a
, key_b b
, fld1 bind_fld1
, fld2 bind_fld2
FROM
tbl
)
-- Π½Π°Ρ
ΠΎΠ΄ΠΈΠΌ min/max Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ ΠΊΠ»ΡΡΠ°
, cte_max AS (
SELECT
a
, max(bind_fld1) bind_fld1
, min(bind_fld2) bind_fld2
FROM
cte_bind
GROUP BY
a
)
-- ΡΠ²ΡΠ·ΡΠ²Π°Π΅ΠΌ ΠΏΠΎ ΠΏΠ΅ΡΠ²ΠΎΠΌΡ ΠΊΠ»ΡΡΡ ΠΊΠ»ΡΡΠ΅Π²ΡΠ΅ ΠΏΠ°ΡΡ ΠΈ min/max-Π·Π½Π°ΡΠ΅Π½ΠΈΡ
, cte_a_bind AS (
SELECT
cte_bind.a
, cte_bind.b
, cte_max.bind_fld1
, cte_max.bind_fld2
FROM
cte_bind
INNER JOIN
cte_max
ON cte_max.a = cte_bind.a
)
SELECT * FROM cte_a_bind;
Ukuvandlakanya umgangatho wesicelo, makhe senze iseti yedatha engenasizathu:
CREATE TABLE tbl AS
SELECT
(random() * 1000)::integer key_a
, (random() * 1000)::integer key_b
, (random() * 10000)::integer fld1
, (random() * 10000)::integer fld2
FROM
generate_series(1, 10000);
CREATE INDEX ON tbl(key_a, key_b);
Kuvela ukuba ukufunda idatha kuthathe ngaphantsi kwekota yexesha Ukwenziwa kombuzo:
Ukuyicalula iqhekeza ngeqhekeza
Masijonge ngakumbi isicelo kwaye sixakeke:
- Kutheni i-RECURSIVE apha ukuba azikho ii-CTEs eziphindaphindayo?
- Kutheni le nto iqela le-min/max amaxabiso kwi-CTE eyahlukileyo ukuba ibotshelelwe kwisampulu yoqobo?
+ 25% ixesha - Kutheni usebenzisa i-'KHETHA * FROM 'engenamiqathango ekupheleni ukuphinda i-CTE yangaphambili?
+ 14% ixesha
Kule meko, sibe nethamsanqa kakhulu ukuba i-Hash Joyina ikhethelwe uqhagamshelo, kwaye hayi i-Nested Loop, kuba ke besingayi kufumana nje ipasi enye ye-CTE Scan, kodwa i-10K!
kancinci malunga CTE ScanApha kufuneka siyikhumbule loo nto I-CTE Scan iyafana neSeq Scan - oko kukuthi, akukho indexing, kodwa kuphela uphendlo olupheleleyo, oluya kufuna 10K x 0.3ms = 3000ms kwimijikelo nge cte_max okanye 1K x 1.5ms = 1500ms xa ulophu nge cte_bind!
Ngokwenene, ubufuna ukufumana ntoni ngenxa yoko? Ewe, ngokuqhelekileyo lo ngumbuzo ovela kwindawo ethile kwimizuzu ye-5 yokuhlalutya imibuzo "yemigangatho emithathu".
Sasifuna ukuvelisa isibini esisitshixo esikhethekileyo min/ubuninzi ukusuka kwiqela nge key_a.
Ngoko masiyisebenzisele oku
SELECT DISTINCT ON(key_a, key_b)
key_a a
, key_b b
, max(fld1) OVER(w) bind_fld1
, min(fld2) OVER(w) bind_fld2
FROM
tbl
WINDOW
w AS (PARTITION BY key_a);
Ekubeni idatha yokufunda kuzo zombini iinketho ithatha okufanayo malunga ne-4-5ms, ngoko lonke ixesha lethu lizuza -32% - oku kukwimo ecocekileyo umthwalo ususiwe kwisiseko se-CPU, ukuba eso sicelo senziwe rhoqo ngokwaneleyo.
Ngokubanzi, akufanele unyanzelise isiseko ukuba "uthwale umjikelo, qengqeleka isikwere."
umthombo: www.habr.com