PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: CTE x CTE

เจฎเฉ‡เจฐเฉ‡ เจ•เฉฐเจฎ เจฆเฉ€ เจฒเจพเจˆเจจ เจฆเฉ‡ เจ•เจพเจฐเจจ, เจฎเฉˆเจจเฉ‚เฉฐ เจ‰เจนเจจเจพเจ‚ เจธเจฅเจฟเจคเฉ€เจ†เจ‚ เจจเจพเจฒ เจจเจœเจฟเฉฑเจ เจฃเจพ เจชเฉˆเจ‚เจฆเจพ เจนเฉˆ เจœเจฆเฉ‹เจ‚ เจ‡เฉฑเจ• เจกเจฟเจตเฉˆเจฒเจชเจฐ เจ‡เฉฑเจ• เจฌเฉ‡เจจเจคเฉ€ เจฒเจฟเจ–เจฆเจพ เจนเฉˆ เจ…เจคเฉ‡ เจธเฉ‹เจšเจฆเจพ เจนเฉˆ "เจ…เจงเจพเจฐ เจšเฉเจธเจค เจนเฉˆ, เจ‡เจน เจธเจญ เจ•เฉเจ เจ†เจชเจฃเฉ‡ เจ†เจช เจธเฉฐเจญเจพเจฒ เจธเจ•เจฆเจพ เจนเฉˆ!ยซ

เจ•เฉเจ เจฎเจพเจฎเจฒเจฟเจ†เจ‚ เจตเจฟเฉฑเจš (เจ…เฉฐเจธเจผเจ• เจคเฉŒเจฐ 'เจคเฉ‡ เจกเฉ‡เจŸเจพเจฌเฉ‡เจธ เจฆเฉ€เจ†เจ‚ เจธเจฎเจฐเฉฑเจฅเจพเจตเจพเจ‚ เจฆเฉ€ เจ…เจ—เจฟเจ†เจจเจคเจพ เจคเฉ‹เจ‚, เจ…เฉฐเจธเจผเจ• เจคเฉŒเจฐ 'เจคเฉ‡ เจธเจฎเฉ‡เจ‚ เจคเฉ‹เจ‚ เจชเจนเจฟเจฒเจพเจ‚ เจ…เจจเฉเจ•เฉ‚เจฒเจคเจพเจตเจพเจ‚ เจคเฉ‹เจ‚), เจ‡เจน เจชเจนเฉเฉฐเจš "เจซเฉเจฐเฉˆเจ‚เจ•เจจเจธเจŸเจพเจˆเจจเจœเจผ" เจฆเฉ€ เจฆเจฟเฉฑเจ– เจตเฉฑเจฒ เจฒเฉˆ เจœเจพเจ‚เจฆเฉ€ เจนเฉˆเฅค

เจชเจนเจฟเจฒเจพเจ‚, เจฎเฉˆเจ‚ เจ…เจœเจฟเจนเฉ€ เจฌเฉ‡เจจเจคเฉ€ เจฆเฉ€ เจ‡เฉฑเจ• เจ‰เจฆเจพเจนเจฐเจฃ เจฆเฉ‡เจตเจพเจ‚เจ—เจพ:

-- ะดะปั ะบะฐะถะดะพะน ะบะปัŽั‡ะตะฒะพะน ะฟะฐั€ั‹ ะฝะฐั…ะพะดะธะผ ะฐััะพั†ะธะธั€ะพะฒะฐะฝะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั ะฟะพะปะตะน
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);

เจ‡เจน เจชเจคเจพ เจšเจฒเจฆเจพ เจนเฉˆ เจ•เจฟ เจกเฉ‡เจŸเจพ เจจเฉ‚เฉฐ เจชเฉœเฉเจนเจจ เจตเจฟเฉฑเจš เจ‡เฉฑเจ• เจšเฉŒเจฅเจพเจˆ เจคเฉ‹เจ‚ เจตเฉ€ เจ˜เฉฑเจŸ เจธเจฎเจพเจ‚ เจฒเฉฑเจ—เจฟเจ† เจชเฉเฉฑเจ›เจ—เจฟเฉฑเจ› เจเจ—เจœเจผเฉ€เจ•เจฟเจŠเจธเจผเจจ:

PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: CTE x CTE[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจŸเฉเจ•เฉœเฉ‡-เจŸเฉเจ•เฉœเฉ‡ เจ•เจฐเจ•เฉ‡ เจ‡เจธ เจจเฉ‚เฉฐ เจตเฉฑเจ–เจฐเจพ เจ•เจฐเจจเจพ

เจ†เจ“ เจฌเฉ‡เจจเจคเฉ€ 'เจคเฉ‡ เจ‡เฉฑเจ• เจกเฉ‚เฉฐเจ˜เจพเจˆ เจจเจพเจฒ เจตเจฟเจšเจพเจฐ เจ•เจฐเฉ€เจ เจ…เจคเฉ‡ เจ‰เจฒเจเจฃ เจตเจฟเฉฑเจš เจฐเจนเฉ‹:

  1. เจœเฉ‡เจ•เจฐ เจ•เฉ‹เจˆ เจ†เจตเจฐเจคเฉ€ CTE เจจเจนเฉ€เจ‚ เจนเจจ เจคเจพเจ‚ เจ‡เฉฑเจฅเฉ‡ WITH RECURSIVE เจ•เจฟเจ‰เจ‚ เจนเฉˆ?
  2. เจ‡เฉฑเจ• เจตเฉฑเจ–เจฐเฉ‡ CTE เจตเจฟเฉฑเจš เจธเจฎเฉ‚เจน เจ˜เฉฑเจŸเฉ‹-เจ˜เฉฑเจŸ/เจ…เจงเจฟเจ•เจคเจฎ เจฎเฉเฉฑเจฒ เจ•เจฟเจ‰เจ‚ เจนเจจ เจœเฉ‡เจ•เจฐ เจ‰เจน เจซเจฟเจฐ เจตเฉ€ เจฎเฉ‚เจฒ เจจเจฎเฉ‚เจจเฉ‡ เจจเจพเจฒ เจฌเฉฐเจจเฉเจนเฉ‡ เจนเฉ‹เจ เจนเจจ?
    +25% เจธเจฎเจพเจ‚
  3. เจชเจฟเจ›เจฒเฉ‡ CTE เจจเฉ‚เฉฐ เจฆเฉเจนเจฐเจพเจ‰เจฃ เจฒเจˆ เจ…เฉฐเจค เจตเจฟเฉฑเจš เจฌเจฟเจจเจพเจ‚ เจธเจผเจฐเจค 'SELECT * FROM' เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฟเจ‰เจ‚ เจ•เจฐเฉ€เจ?
    +14% เจธเจฎเจพเจ‚

เจ‡เจธ เจฎเจพเจฎเจฒเฉ‡ เจตเจฟเฉฑเจš, เจ…เจธเฉ€เจ‚ เจฌเจนเฉเจค เจ–เฉเจธเจผเจ•เจฟเจธเจฎเจค เจธเฉ€ เจ•เจฟ เจ•เจจเฉˆเจ•เจธเจผเจจ เจฒเจˆ Hash Join เจจเฉ‚เฉฐ เจšเฉเจฃเจฟเจ† เจ—เจฟเจ† เจธเฉ€, เจจเจพ เจ•เจฟ Nested Loop, เจ•เจฟเจ‰เจ‚เจ•เจฟ เจ‰เจฆเฉ‹เจ‚ เจธเจพเจจเฉ‚เฉฐ เจธเจฟเจฐเจซเจผ เจ‡เฉฑเจ• CTE เจธเจ•เฉˆเจจ เจชเจพเจธ เจจเจนเฉ€เจ‚, เจธเจ—เฉ‹เจ‚ 10K เจชเฉเจฐเจพเจชเจค เจนเฉ‹เจ เจนเฉ‹เจฃเจ—เฉ‡!

เจธเฉ€เจŸเฉ€เจˆ เจธเจ•เฉˆเจจ เจฌเจพเจฐเฉ‡ เจฅเฉ‹เฉœเฉเจนเจพ เจœเจฟเจนเจพเจ‡เฉฑเจฅเฉ‡ เจธเจพเจจเฉ‚เฉฐ เจ‡เจน เจฏเจพเจฆ เจฐเฉฑเจ–เจฃเจพ เจšเจพเจนเฉ€เจฆเจพ เจนเฉˆ CTE เจธเจ•เฉˆเจจ Seq เจธเจ•เฉˆเจจ เจฆเฉ‡ เจธเจฎเจพเจจ เจนเฉˆ - เจญเจพเจต, เจ•เฉ‹เจˆ เจ‡เฉฐเจกเฉˆเจ•เจธเจฟเฉฐเจ— เจจเจนเฉ€เจ‚, เจชเจฐ เจธเจฟเจฐเจซ เจ‡เฉฑเจ• เจชเฉ‚เจฐเฉ€ เจ–เฉ‹เจœ, เจœเจฟเจธเจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉ‹เจตเฉ‡เจ—เฉ€ 10K x 0.3ms = 3000ms cte_max เจฆเฉเจ†เจฐเจพ เจšเฉฑเจ•เจฐ เจฒเจˆ เจœ 1K x 1.5ms = 1500ms เจœเจฆเฉ‹เจ‚ cte_bind เจฆเฉเจ†เจฐเจพ เจฒเฉ‚เจช เจ•เฉ€เจคเจพ เจœเจพเจ‚เจฆเจพ เจนเฉˆ!
เจ…เจธเจฒ เจตเจฟเฉฑเจš, เจคเฉเจธเฉ€เจ‚ เจจเจคเฉ€เจœเฉ‡ เจตเจœเฉ‹เจ‚ เจ•เฉ€ เจชเฉเจฐเจพเจชเจค เจ•เจฐเจจเจพ เจšเจพเจนเฉเฉฐเจฆเฉ‡ เจธเฉ€? เจนเจพเจ‚, เจ†เจฎ เจคเฉŒเจฐ 'เจคเฉ‡ เจ‡เจน เจ‰เจน เจธเจตเจพเจฒ เจนเฉˆ เจœเฉ‹ "เจคเจฟเฉฐเจจ-เจฎเฉฐเจœเจผเจฒเจพ" เจธเจตเจพเจฒเจพเจ‚ เจฆเจพ เจตเจฟเจธเจผเจฒเฉ‡เจธเจผเจฃ เจ•เจฐเจจ เจฆเฉ‡ 5เจตเฉ‡เจ‚ เจฎเจฟเฉฐเจŸ เจตเจฟเฉฑเจš เจ•เจฟเจคเฉ‡ เจ†เจ‰เจ‚เจฆเจพ เจนเฉˆเฅค

เจ…เจธเฉ€เจ‚ เจนเจฐเฉ‡เจ• เจตเจฟเจฒเฉฑเจ–เจฃ เจ•เฉเฉฐเจœเฉ€ เจœเฉ‹เฉœเฉ‡ เจฒเจˆ เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจ•เจฐเจจเจพ เจšเจพเจนเฉเฉฐเจฆเฉ‡ เจธเฉ€ 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);

PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: CTE x CTE
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ•เจฟเจ‰เจ‚เจ•เจฟ เจฆเฉ‹เจตเจพเจ‚ เจตเจฟเจ•เจฒเจชเจพเจ‚ เจตเจฟเฉฑเจš เจกเฉ‡เจŸเจพ เจจเฉ‚เฉฐ เจชเฉœเฉเจนเจจ เจตเจฟเฉฑเจš เจฒเจ—เจญเจ— 4-5ms เจฒเฉฑเจ—เจฆเฉ‡ เจนเจจ, เจซเจฟเจฐ เจธเจพเจกเจพ เจธเจพเจฐเจพ เจธเจฎเจพเจ‚ เจฒเจพเจญ เจนเฉเฉฐเจฆเจพ เจนเฉˆ -32% - เจ‡เจน เจ‡เจธเจฆเฉ‡ เจธเจผเฉเฉฑเจง เจฐเฉ‚เจช เจตเจฟเฉฑเจš เจนเฉˆ เจฌเฉ‡เจธ CPU เจคเฉ‹เจ‚ เจฒเฉ‹เจก เจนเจŸเจพเจ‡เจ† เจ—เจฟเจ†, เจœเฉ‡เจ•เจฐ เจ…เจœเจฟเจนเฉ€ เจฌเฉ‡เจจเจคเฉ€ เจจเฉ‚เฉฐ เจ…เจ•เจธเจฐ เจ•เจพเจซเจผเฉ€ เจฒเจพเจ—เฉ‚ เจ•เฉ€เจคเจพ เจœเจพเจ‚เจฆเจพ เจนเฉˆเฅค

เจ†เจฎ เจคเฉŒเจฐ 'เจคเฉ‡, เจคเฉเจนเจพเจจเฉ‚เฉฐ เจฌเฉ‡เจธ เจจเฉ‚เฉฐ "เจ—เฉ‹เจฒ เจจเฉ‚เฉฐ เจฒเฉˆ เจ•เฉ‡ เจœเจพเจ“, เจตเจฐเจ— เจจเฉ‚เฉฐ เจฐเฉ‹เจฒ เจ•เจฐเฉ‹" เจฒเจˆ เจฎเจœเจฌเฉ‚เจฐ เจจเจนเฉ€เจ‚ เจ•เจฐเจจเจพ เจšเจพเจนเฉ€เจฆเจพเฅค

เจธเจฐเฉ‹เจค: www.habr.com

เจ‡เฉฑเจ• เจŸเจฟเฉฑเจชเจฃเฉ€ เจœเฉ‹เฉœเฉ‹