เชฎเชพเชฐเชพ เชเชพเชฎเชจเซ เชฒเชพเชเชจเชจเซ เชฒเซเชงเซ, เชเซเชฏเชพเชฐเซ เชตเชฟเชเชพเชธเชเชฐเซเชคเชพ เชตเชฟเชจเชเชคเซ เชฒเชเซ เชเซ เช เชจเซ เชตเชฟเชเชพเชฐเซ เชเซ เชคเซเชฏเชพเชฐเซ เชฎเชพเชฐเซ เชชเชฐเชฟเชธเซเชฅเชฟเชคเชฟเชเชจเซ เชธเชพเชฎเชจเซ เชเชฐเชตเซ เชชเชกเซ เชเซ.เชเชงเชพเชฐ เชธเซเชฎเชพเชฐเซเช เชเซ, เชคเซ เชฌเชงเซเช เชเชพเชคเซ เชธเชเชญเชพเชณเซ เชถเชเซ เชเซ!ยซ
เชเซเชเชฒเชพเช เชเชฟเชธเซเชธเชพเชเชฎเชพเช (เช
เชเชถเชคเช เชกเซเชเชพเชฌเซเชเชจเซ เชเซเชทเชฎเชคเชพเชเชจเซ เช
เชเซเชเชพเชจเชคเชพเชฅเซ, เช
เชเชถเชคเช เช
เชเชพเชณ เชเชชเซเชเชฟเชฎเชพเชเชเซเชถเชจเชฅเซ), เช เช
เชญเชฟเชเชฎ "เชซเซเชฐเซเชจเซเชเซเชธเซเชเชพเชเชจ" เชจเชพ เชฆเซเชเชพเชต เชคเชฐเชซ เชฆเซเชฐเซ เชเชพเชฏ เชเซ.
เชชเซเชฐเชฅเชฎ, เชนเซเช เชเชตเซ เชตเชฟเชจเชเชคเซเชจเซเช เชเชฆเชพเชนเชฐเชฃ เชเชชเซเชถ:
-- ะดะปั ะบะฐะถะดะพะน ะบะปััะตะฒะพะน ะฟะฐัั ะฝะฐั
ะพะดะธะผ ะฐััะพัะธะธัะพะฒะฐะฝะฝัะต ะทะฝะฐัะตะฝะธั ะฟะพะปะตะน
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;
เชตเชฟเชจเชเชคเซเชจเซ เชเซเชฃเชตเชคเซเชคเชพเชจเซเช เชจเซเชเชงเชชเชพเชคเซเชฐ เชฎเซเชฒเซเชฏเชพเชเชเชจ เชเชฐเชตเชพ เชฎเชพเชเซ, เชเชพเชฒเซ เชเซเชเชฒเชพเช เชฎเชจเชธเซเชตเซ เชกเซเชเชพ เชธเซเช เชฌเชจเชพเชตเซเช:
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);
เชคเซ เชคเชพเชฐเชฃ เชเชชเซ เชเซ เชเซ เชกเซเชเชพ เชตเชพเชเชเชตเชพเชฎเชพเช เชเช เชเซเชตเชพเชฐเซเชเชฐ เชเชฐเชคเชพ เชเชเซ เชธเชฎเชฏ เชฒเชพเชเซเชฏเซ เชเซเชตเซเชฐเซ เช เชฎเชฒ:
เชเซเชเชกเซ เชเซเชเชกเซ เชคเซเชจเซ เช เชฒเช เชเชฐเซเชจเซ เชฒเช เชเชตเชพเชจเซเช
เชเชพเชฒเซ เชตเชฟเชจเชเชคเซ เชชเชฐ เชจเชเซเชเชฅเซ เชจเชเชฐ เชเชฐเซเช เช เชจเซ เชฎเซเชเชเชตเชฃเชฎเชพเช เชฐเชนเซเช:
- เชเซ เชเซเช เชชเซเชจเชฐเชพเชตเชฐเซเชคเชฟเชค CTE เชจเชพ เชนเซเชฏ เชคเซ เช เชนเซเช WITH RECURSIVE เชถเชพ เชฎเชพเชเซ เชเซ?
- เชเช เช
เชฒเช CTE เชฎเชพเช เชฒเชเซเชคเซเชคเชฎ/เชฎเชนเชคเซเชคเชฎ เชฎเซเชฒเซเชฏเซเชจเซเช เชเซเชฅ เชถเชพ เชฎเชพเชเซ เชเซ เชคเซเช เชเซเชเชชเชฃ เชฐเซเชคเซ เชฎเซเชณ เชจเชฎเซเชจเชพ เชธเชพเชฅเซ เชเซเชกเชพเชฏเซเชฒเชพ เชนเซเชฏ?
+25% เชธเชฎเชฏ - เช
เชเชพเชเชจเชพ CTE เชจเชพ เช
เชเชคเซ เชฌเชฟเชจเชถเชฐเชคเซ 'SELECT * FROM' เชจเซ เชเชชเชฏเซเช เชถเชพ เชฎเชพเชเซ เชเชฐเชตเซ?
+14% เชธเชฎเชฏ
เช เชเชฟเชธเซเชธเชพเชฎเชพเช, เช เชฎเซ เชเซเชฌ เชจเชธเซเชฌเชฆเชพเชฐ เชนเชคเชพ เชเซ เชเชจเซเชเซเชถเชจ เชฎเชพเชเซ Hash Join เชชเชธเชเชฆ เชเชฐเชตเชพเชฎเชพเช เชเชตเซเชฏเซเช เชนเชคเซเช, เชจเซเชธเซเชเซเชก เชฒเซเชช เชฎเชพเชเซ เชจเชนเซเช, เชเชพเชฐเชฃ เชเซ เชชเชเซ เช เชฎเชจเซ เชฎเชพเชคเซเชฐ เชเช CTE เชธเซเชเซเชจ เชชเชพเชธ เชจเชนเซเช, เชชเชฐเชเชคเซ 10K เชชเซเชฐเชพเชชเซเชค เชฅเชฏเชพ เชนเซเชค!
CTE เชธเซเชเซเชจ เชตเชฟเชถเซ เชฅเซเชกเซเชเช
เชนเซเช เชเชชเชฃเซ เชคเซ เชฏเชพเชฆ เชฐเชพเชเชตเซเช เชเซเชเช CTE เชธเซเชเซเชจ Seq Scan เชเซเชตเซเช เช เชเซ - เชเชเชฒเซ เชเซ, เชเซเช เช
เชจเซเชเซเชฐเชฎเชฃเชฟเชเชพ เชจเชนเซเช, เชชเชฐเชเชคเซ เชฎเชพเชคเซเชฐ เชเช เชธเชเชชเซเชฐเซเชฃ เชถเซเชง, เชเซเชจเซ เชเชฐเซเชฐ เชชเชกเชถเซ 10K x 0.3ms = 3000ms cte_max เชฆเซเชตเชพเชฐเชพ เชเชเซเชฐ เชฎเชพเชเซ เช
เชฅเชตเชพ 1K x 1.5ms = 1500ms cte_bind เชฆเซเชตเชพเชฐเชพ เชฒเซเชช เชเชฐเชคเซ เชตเชเชคเซ!
เชตเชพเชธเซเชคเชตเชฎเชพเช, เชคเชฎเซ เชชเชฐเชฟเชฃเชพเชฎ เชคเชฐเซเชเซ เชถเซเช เชฎเซเชณเชตเชตเชพ เชฎเชพเชเชเชคเชพ เชนเชคเชพ? เชนเชพ, เชธเชพเชฎเชพเชจเซเชฏ เชฐเซเชคเซ เช เชคเซ เชชเซเชฐเชถเซเชจ เชเซ เชเซ "เชคเซเชฐเชฃ-เชตเชพเชฐเซเชคเชพ" เชชเซเชฐเชถเซเชจเซเชจเซเช เชตเชฟเชถเซเชฒเซเชทเชฃ เชเชฐเชตเชพเชจเซ 5เชฎเซ เชฎเชฟเชจเชฟเชเชฎเชพเช เชเซเชฏเชพเชเช เชเชตเซ เชเซ.
เช
เชฎเซ เชฆเชฐเซเช เช
เชจเชจเซเชฏ เชเซ เชเซเชกเซ เชฎเชพเชเซ เชเชเชเชชเซเช เชเชฐเชตเชพ เชฎเชพเชเชเซเช เชเซเช เชเซ_เช เชฆเซเชตเชพเชฐเชพ เชเซเชฅเชฎเชพเชเชฅเซ เชจเซเชฏเซเชจเชคเชฎ/เชฎเชนเชคเซเชคเชฎ.
เชคเซ เชเชพเชฒเซ เช เชฎเชพเชเซ เชคเซเชจเซ เชเชชเชฏเซเช เชเชฐเซเช
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);
เชฌเชเชจเซ เชตเชฟเชเชฒเซเชชเซเชฎเชพเช เชกเซเชเชพ เชตเชพเชเชเชตเชพเชฎเชพเช เชฒเชเชญเช 4-5ms เชเซเชเชฒเซ เชธเชฎเชฏ เชฒเชพเชเซ เชเซ, เชคเซ เชชเชเซ เช เชฎเชพเชฐเซ เชฌเชงเซ เชธเชฎเชฏ เชฒเชพเชญ เชฅเชพเชฏ เชเซ -32% - เช เชคเซเชจเชพ เชถเซเชฆเซเชง เชธเซเชตเชฐเซเชชเชฎเชพเช เชเซ เชเชงเชพเชฐ CPU เชฎเชพเชเชฅเซ เชฒเซเชก เชฆเซเชฐ เชเชฐเซเชฏเซ, เชเซ เชเชตเซ เชตเชฟเชจเชเชคเซ เชเชฃเซ เชตเชเชค เชชเชฐเซเชฏเชพเชชเซเชค เชฐเซเชคเซ เชเชฒเชพเชตเชตเชพเชฎเชพเช เชเชตเซ เชเซ.
เชธเชพเชฎเชพเชจเซเชฏ เชฐเซเชคเซ, เชคเชฎเชพเชฐเซ เชเชงเชพเชฐเชจเซ "เชเซเชณเชพเชเชพเชฐ เชตเชนเชจ เชเชฐเชตเชพ, เชเซเชฐเชธ เชเชเชจเซ เชฐเซเชฒ เชเชฐเชตเชพ" เชฎเชพเชเซ เชฆเชฌเชพเชฃ เชเชฐเชตเซเช เชเซเชเช เชจเชนเซเช.
เชธเซเชฐเซเชธ: www.habr.com