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