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[แƒœแƒแƒฎแƒ”แƒ— description.tensor.ru]

แƒœแƒแƒฌแƒ˜แƒš-แƒœแƒแƒฌแƒ˜แƒš แƒ˜แƒจแƒšแƒ”แƒ‘แƒ

แƒ›แƒแƒ“แƒ˜แƒ—, แƒฃแƒคแƒ แƒ แƒแƒฎแƒšแƒแƒก แƒ›แƒ˜แƒ•แƒฎแƒ”แƒ“แƒแƒ— แƒ—แƒฎแƒแƒ•แƒœแƒแƒก แƒ“แƒ แƒ“แƒแƒ•แƒคแƒ˜แƒฅแƒ แƒ“แƒ”แƒ—:

  1. แƒ แƒแƒขแƒแƒ› แƒแƒ แƒ˜แƒก WITH RECURSIVE แƒแƒฅ, แƒ—แƒฃ แƒแƒ  แƒแƒ แƒ˜แƒก แƒ แƒ”แƒ™แƒฃแƒ แƒกแƒ˜แƒฃแƒšแƒ˜ CTE?
  2. แƒ แƒแƒขแƒแƒ› แƒ“แƒแƒแƒฏแƒ’แƒฃแƒคแƒ”แƒ— แƒ›แƒ˜แƒœ/แƒ›แƒแƒฅแƒก แƒ›แƒœแƒ˜แƒจแƒ•แƒœแƒ”แƒšแƒแƒ‘แƒ”แƒ‘แƒ˜ แƒชแƒแƒšแƒ™แƒ” CTE-แƒจแƒ˜, แƒ—แƒฃ แƒ˜แƒกแƒ˜แƒœแƒ˜ แƒ›แƒแƒ˜แƒœแƒช แƒ›แƒ˜แƒ‘แƒ›แƒฃแƒšแƒ˜แƒ แƒแƒ แƒ˜แƒ’แƒ˜แƒœแƒแƒšแƒฃแƒ  แƒœแƒ˜แƒ›แƒฃแƒจแƒ–แƒ”?
    +25% แƒ“แƒ แƒ
  3. แƒ แƒแƒขแƒแƒ› แƒ’แƒแƒ›แƒแƒ•แƒ˜แƒงแƒ”แƒœแƒแƒ— แƒฃแƒžแƒ˜แƒ แƒแƒ‘แƒ "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);

PostgreSQL แƒแƒœแƒขแƒ˜แƒžแƒแƒขแƒ”แƒ แƒœแƒ”แƒ‘แƒ˜: CTE x CTE
[แƒœแƒแƒฎแƒ”แƒ— description.tensor.ru]

แƒ•แƒ˜แƒœแƒแƒ˜แƒ“แƒแƒœ แƒแƒ แƒ˜แƒ•แƒ” แƒ•แƒแƒ แƒ˜แƒแƒœแƒขแƒจแƒ˜ แƒ›แƒแƒœแƒแƒชแƒ”แƒ›แƒ”แƒ‘แƒ˜แƒก แƒฌแƒแƒ™แƒ˜แƒ—แƒฎแƒ•แƒแƒก แƒ˜แƒ’แƒ˜แƒ•แƒ” แƒกแƒญแƒ˜แƒ แƒ“แƒ”แƒ‘แƒ แƒ“แƒแƒแƒฎแƒšแƒแƒ”แƒ‘แƒ˜แƒ— 4-5 ms, แƒ›แƒแƒจแƒ˜แƒœ แƒ›แƒ—แƒ”แƒšแƒ˜ แƒฉแƒ•แƒ”แƒœแƒ˜ แƒ“แƒ แƒ แƒ˜แƒ–แƒ แƒ“แƒ”แƒ‘แƒ -32% - แƒ”แƒก แƒแƒ แƒ˜แƒก แƒ›แƒ˜แƒกแƒ˜ แƒกแƒฃแƒคแƒ—แƒ แƒกแƒแƒฎแƒ˜แƒ— แƒ“แƒแƒขแƒ•แƒ˜แƒ แƒ—แƒ•แƒ แƒแƒ›แƒแƒฆแƒ”แƒ‘แƒฃแƒšแƒ˜แƒ แƒ‘แƒแƒ–แƒ˜แƒก CPU-แƒ“แƒแƒœแƒ—แƒฃ แƒแƒกแƒ”แƒ—แƒ˜ แƒ›แƒแƒ—แƒฎแƒแƒ•แƒœแƒ แƒกแƒแƒ™แƒ›แƒแƒ แƒ˜แƒกแƒแƒ“ แƒฎแƒจแƒ˜แƒ แƒแƒ“ แƒจแƒ”แƒกแƒ แƒฃแƒšแƒ“แƒ”แƒ‘แƒ.

แƒ–แƒแƒ’แƒแƒ“แƒแƒ“, แƒ—แƒฅแƒ•แƒ”แƒœ แƒแƒ  แƒฃแƒœแƒ“แƒ แƒแƒ˜แƒซแƒฃแƒšแƒแƒ— แƒกแƒแƒคแƒฃแƒซแƒ•แƒ”แƒšแƒ˜ "แƒแƒขแƒแƒ แƒแƒก แƒ›แƒ แƒ’แƒ•แƒแƒšแƒ˜, แƒ’แƒแƒแƒคแƒแƒ แƒ—แƒแƒ•แƒแƒก แƒ™แƒ•แƒแƒ“แƒ แƒแƒขแƒ˜".

แƒฌแƒงแƒแƒ แƒ: www.habr.com

แƒแƒฎแƒแƒšแƒ˜ แƒ™แƒแƒ›แƒ”แƒœแƒขแƒแƒ แƒ˜แƒก แƒ“แƒแƒ›แƒแƒขแƒ”แƒ‘แƒ