Mar thoradh air an loidhne obrach agam, feumaidh mi dèiligeadh ri suidheachaidhean nuair a bhios leasaiche a’ sgrìobhadh iarrtas agus a’ smaoineachadh “Tha am bonn spaideil, is urrainn dha a h-uile càil a làimhseachadh fhèin!«
Ann an cuid de chùisean (gu ìre air sgàth aineolas air comasan an stòr-dàta, gu ìre bho ro-luath optimizations), dòigh-obrach seo a 'leantainn gu coltas "Frankensteins".
An toiseach, bheir mi eisimpleir de leithid de dh’ iarrtas:
-- для каждой ключевой пары находим ассоциированные значения полей
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;
Gus measadh susbainteach a dhèanamh air càileachd iarrtas, cruthaichidh sinn seata dàta neo-riaghailteach:
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);
Tha e a 'tionndadh a-mach sin thug leughadh an dàta nas lugha na cairteal den ùine cur an gnìomh ceiste:
A thoirt às a chèile pìos air pìos
Bheir sinn sùil nas mionaidiche air an iarrtas agus bidh sinn fo imcheist:
- Carson a tha LE RECURSIVE an seo mura h-eil CTEn ath-chuairteachaidh ann?
- Carson a tha buidhnean min / max a’ cur luach ann an CTE air leth ma tha iad an uairsin ceangailte ris an t-sampall tùsail co-dhiù?
+25% ùine - Carson a chleachdas tu ‘SELECT * FROM’ gun chumhachan aig deireadh an CTE roimhe seo?
+14% ùine
Anns a ’chùis seo, bha sinn gu math fortanach gun deach Hash Join a thaghadh airson a’ cheangail, agus chan e Nested Loop, oir an uairsin bhiodh sinn air chan e a-mhàin aon chead CTE Scan fhaighinn, ach 10K!
Beagan fiosrachaidh mu CTE ScanAn seo feumaidh sinn cuimhneachadh air sin Tha CTE Scan coltach ri Seq Scan - is e sin, gun chlàr-amais, ach a-mhàin sgrùdadh coileanta, a dh’ fheumadh 10K x 0.3ms = 3000ms airson cuairtean le cte_max no 1K x 1.5ms = 1500ms nuair a lùbadh tu le cte_bind!
Gu fìrinneach, dè a bha thu airson fhaighinn mar thoradh air an sin? Yeah, mar as trice is e seo a’ cheist a thig am bàrr am badeigin anns a’ 5mh mionaid de bhith a’ sgrùdadh cheistean “trì-sgeulachd”.
Bha sinn airson toradh a chuir a-mach airson gach prìomh phaidhir sònraichte min/max bhon bhuidheann le key_a.
Mar sin cleachd sinn e airson seo
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);
Leis gu bheil leughadh dàta anns an dà roghainn a’ toirt an aon rud timcheall air 4-5ms, an uairsin bidh an ùine againn a’ faighinn buannachd -32% - tha seo anns a chruth fhìor-ghlan luchdaich air falbh bhon CPU bunaiteach, ma thèid an leithid de dh'iarrtas a chur gu bàs tric gu leòr.
San fharsaingeachd, cha bu chòir dhut toirt air a’ bhunait “an tè cruinn a chaitheamh, am fear ceàrnagach a roiligeadh.”
Source: www.habr.com