PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™

เปƒเบ™เบฅเบฐเบšเบปเบš ERP เบ—เบตเปˆเบชเบฑเบšเบชเบปเบ™ เบซเบผเบฒเบเบซเบปเบงเปœเปˆเบงเบเบกเบตเบฅเบฑเบเบชเบฐเบ™เบฐเป€เบ›เบฑเบ™เบฅเบณเบ”เบฑเบšเป€เบกเบทเปˆเบญเบงเบฑเบ”เบ–เบธเบ—เบตเปˆเป€เบ›เบฑเบ™เบญเบฑเบ™เบ”เบฝเบงเบเบฑเบ™เบ•เบฑเป‰เบ‡เบขเบนเปˆเปƒเบ™ เบ•เบปเป‰เบ™โ€‹เป„เบกเป‰โ€‹เบ‚เบญเบ‡โ€‹เบชเบฒเบโ€‹เบžเบปเบงโ€‹เบžเบฑเบ™โ€‹เบšเบฑเบ™โ€‹เบžเบฐโ€‹เบšเบธโ€‹เบฅเบธเบ”โ€‹เปเบฅเบฐโ€‹เบฅเบนเบโ€‹เบซเบฅเบฒเบ™โ€‹ - เบ™เบตเป‰โ€‹เปเบกเปˆเบ™โ€‹เป‚เบ„เบ‡โ€‹เบชเป‰เบฒเบ‡โ€‹เบเบฒเบ™โ€‹เบˆเบฑเบ”โ€‹เบ•เบฑเป‰เบ‡โ€‹เบ‚เบญเบ‡โ€‹เบงเบดโ€‹เบชเบฒโ€‹เบซเบฐโ€‹เบเบดเบ” (เบชเบฒโ€‹เบ‚เบฒโ€‹เบ—เบฑเบ‡โ€‹เบซเบกเบปเบ”โ€‹เป€เบซเบผเบปเปˆเบฒโ€‹เบ™เบตเป‰โ€‹, เบžเบฐโ€‹เปเบ™เบโ€‹เปเบฅเบฐโ€‹เบเบธเปˆเบกโ€‹เบเบฒเบ™โ€‹เป€เบฎเบฑเบ”โ€‹เบงเบฝเบโ€‹)โ€‹, เปเบฅเบฐโ€‹เบฅเบฒเบโ€‹เบเบฒเบ™โ€‹เบชเบดเบ™โ€‹เบ„เป‰เบฒโ€‹, เปเบฅเบฐโ€‹เบžเบทเป‰เบ™โ€‹เบ—เบตเปˆโ€‹เบเบฒเบ™โ€‹เป€เบฎเบฑเบ”โ€‹เบงเบฝเบโ€‹, เปเบฅเบฐโ€‹เบžเบนเบกโ€‹เบชเบฒเบ”โ€‹เบ‚เบญเบ‡โ€‹เบˆเบธเบ”โ€‹เบ‚เบฒเบโ€‹, ...

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™

เปƒเบ™เบ„เบงเบฒเบกเป€เบ›เบฑเบ™เบˆเบดเบ‡, เบšเปเปˆเบกเบต เป€เบ‚เบ”เบญเบฑเบ”เบ•เบฐเป‚เบ™เบกเบฑเบ”เบ—เบธเบฅเบฐเบเบดเบ”, เบšเปˆเบญเบ™เบ—เบตเปˆเบˆเบฐเบšเปเปˆเบกเบตเบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™เป€เบ›เบฑเบ™เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบš. เปเบ•เปˆเป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบ—เปˆเบฒเบ™เบšเปเปˆเป„เบ”เป‰เป€เบฎเบฑเบ”เบงเบฝเบ "เบชเปเบฒเบฅเบฑเบšเบ—เบธเบฅเบฐเบเบดเบ”", เบ—เปˆเบฒเบ™เบเบฑเบ‡เบชเบฒเบกเบฒเบ”เบžเบปเบšเบเบฑเบšเบเบฒเบ™เบžเบปเบงเบžเบฑเบ™เปเบšเบšเบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™เป„เบ”เป‰เบขเปˆเบฒเบ‡เบ‡เปˆเบฒเบเบ”เบฒเบ. เบกเบฑเบ™เป€เบ›เบฑเบ™เป€เบฅเบทเปˆเบญเบ‡เบ—เบตเปˆเปœเป‰เบฒเบชเบปเบ™เปƒเบˆ, เปเบกเปˆเบ™เปเบ•เปˆเบ•เบปเป‰เบ™เป„เบกเป‰เบ„เบญเบšเบ„เบปเบง เบซเบผเบทเปเบœเบ™เบŠเบฑเป‰เบ™เบ‚เบญเบ‡เบชเบฐเบ–เบฒเบ™เบ—เบตเปˆเบขเบนเปˆเปƒเบ™เบชเบนเบ™เบเบฒเบ™เบ„เป‰เบฒเบเปเบกเบตเป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ”เบฝเบงเบเบฑเบ™.

เบกเบตเบซเบผเบฒเบเบงเบดเบ—เบตเบ—เบตเปˆเบˆเบฐเป€เบเบฑเบšเบฎเบฑเบเบชเบฒเบ•เบปเป‰เบ™เป„เบกเป‰เบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเป„เบงเป‰เปƒเบ™ DBMS, เปเบ•เปˆเบกเบทเป‰เบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบชเบธเบกเปƒเบชเปˆเบ—เบฒเบ‡เป€เบฅเบทเบญเบเบ”เบฝเบง:

CREATE TABLE hier(
  id
    integer
      PRIMARY KEY
, pid
    integer
      REFERENCES hier
, data
    json
);

CREATE INDEX ON hier(pid); -- ะฝะต ะทะฐะฑั‹ะฒะฐะตะผ, ั‡ั‚ะพ FK ะฝะต ะฟะพะดั€ะฐะทัƒะผะตะฒะฐะตั‚ ะฐะฒั‚ะพัะพะทะดะฐะฝะธะต ะธะฝะดะตะบัะฐ, ะฒ ะพั‚ะปะธั‡ะธะต ะพั‚ PK

เปเบฅเบฐเปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆเบ—เปˆเบฒเบ™เบเปเบฒเบฅเบฑเบ‡เป€เบšเบดเปˆเบ‡เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ„เบงเบฒเบกเป€เบฅเบดเบเบ‚เบญเบ‡เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™, เบกเบฑเบ™เบฅเปเบ–เป‰เบฒเบขเปˆเบฒเบ‡เบญเบปเบ”เบ—เบปเบ™เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเป„เบ›เป€เบšเบดเปˆเบ‡เบงเบดเบ—เบตเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ—เบตเปˆ "เป‚เบ‡เปˆ" เบ‚เบญเบ‡เป€เบˆเบปเป‰เบฒเบเบฑเบšเป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเบˆเบฐเป€เบ›เบฑเบ™เปเบ™เบงเปƒเบ”.

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™
เปƒเบซเป‰เป€เบšเบดเปˆเบ‡เบšเบฑเบ™เบซเบฒเบ—เบปเปˆเบงเป„เบ›เบ—เบตเปˆเป€เบเบตเบ”เบ‚เบทเป‰เบ™, เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒเปƒเบ™ SQL, เปเบฅเบฐเบžเบฐเบเบฒเบเบฒเบกเบ›เบฑเบšเบ›เบธเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒ.

#1. เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”?

เปƒเบซเป‰เบžเบงเบเป€เบฎเบปเบฒ, เบชเปเบฒเบฅเบฑเบšเบ„เปเบฒเบ™เบดเบเบฒเบก, เบเบญเบกเบฎเบฑเบšเบงเปˆเบฒเป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ™เบตเป‰เบˆเบฐเบชเบฐเบ—เป‰เบญเบ™เปƒเบซเป‰เป€เบซเบฑเบ™ subordination เบ‚เบญเบ‡เบžเบฐเปเบ™เบเปƒเบ™เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ‚เบญเบ‡เบญเบปเบ‡เบเบฒเบ™เบˆเบฑเบ”เบ•เบฑเป‰เบ‡: เบžเบฐเปเบ™เบเบเบฒเบ™, เบžเบฐเปเบ™เบ, เบ‚เบฐเปเปœเบ‡เบเบฒเบ™, เบชเบฒเบ‚เบฒ, เบเบธเปˆเบกเป€เบฎเบฑเบ”เบงเบฝเบ ... - เปƒเบ”เบเปเปˆเบ•เบฒเบกเบ—เบตเปˆเบ—เปˆเบฒเบ™เป‚เบ—เบซเบฒเบžเบงเบเป€เบ‚เบปเบฒ.
PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™

เบ—เปเบฒเบญเบดเบ”, เปƒเบซเป‰เบชเป‰เบฒเบ‡ 'เบ•เบปเป‰เบ™เป„เบกเป‰' เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเบ‚เบญเบ‡เบญเบปเบ‡เบ›เบฐเบเบญเบš 10K

INSERT INTO hier
WITH RECURSIVE T AS (
  SELECT
    1::integer id
  , '{1}'::integer[] pids
UNION ALL
  SELECT
    id + 1
  , pids[1:(random() * array_length(pids, 1))::integer] || (id + 1)
  FROM
    T
  WHERE
    id < 10000
)
SELECT
  pids[array_length(pids, 1)] id
, pids[array_length(pids, 1) - 1] pid
FROM
  T;

เปƒเบซเป‰เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ”เป‰เบงเบเบงเบฝเบเบ‡เบฒเบ™เบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบเบ—เบตเปˆเบชเบธเบ” - เบŠเบญเบเบซเบฒเบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”เบ—เบตเปˆเป€เบฎเบฑเบ”เบงเบฝเบเบขเบนเปˆเปƒเบ™เบ‚เบฐเปเบซเบ™เบ‡เบเบฒเบ™เบชเบฐเป€เบžเบฒเบฐ, เบซเบผเบทเปƒเบ™เป€เบ‡เบทเปˆเบญเบ™เป„เบ‚เบ‚เบญเบ‡เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™ - เบŠเบญเบเบซเบฒเป€เบ”เบฑเบเบ™เป‰เบญเบเบ—เบฑเบ‡เบซเบกเบปเบ”เบ‚เบญเบ‡ node. เบกเบฑเบ™เบเปเปˆเบˆเบฐเป€เบ›เบฑเบ™เบเบฒเบ™เบ”เบตเบ—เบตเปˆเบˆเบฐเป„เบ”เป‰เบฎเบฑเบš "เบ„เบงเบฒเบกเป€เบฅเบดเบ" เบ‚เบญเบ‡เบฅเบนเบเบซเบฅเบฒเบ™ ... เบ—เบฑเบ‡เบซเบกเบปเบ”เบ™เบตเป‰เบญเบฒเบ”เบˆเบฐเบกเบตเบ„เบงเบฒเบกเบˆเปเบฒเป€เบ›เบฑเบ™, เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบเบปเบเบ•เบปเบงเบขเปˆเบฒเบ‡, เบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡เบšเบฒเบ‡เบ›เบฐเป€เบžเบ”. เบเบฒเบ™เบ„เบฑเบ”เป€เบฅเบทเบญเบเบ—เบตเปˆเบชเบฑเบšเบชเบปเบ™เป‚เบ”เบเบญเบตเบ‡เปƒเบชเปˆเบšเบฑเบ™เบŠเบตเบฅเบฒเบเบŠเบทเปˆเบ‚เบญเบ‡เบšเบฑเบ”เบ›เบฐเบˆเปเบฒเบ•เบปเบงเบ‚เบญเบ‡เบžเบฐเบ™เบฑเบเบ‡เบฒเบ™เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰.

เบ—เบธเบเบขเปˆเบฒเบ‡เบ„เบปเบ‡เบˆเบฐเบ”เบตเบ–เป‰เบฒเบกเบตเบฅเบนเบเบซเบฅเบฒเบ™เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบžเบฝเบ‡เปเบ•เปˆเบชเบญเบ‡เบชเบฒเบกเบฅเบฐเบ”เบฑเบš เปเบฅเบฐเบ•เบปเบงเป€เบฅเบเปเบกเปˆเบ™เบžเบฒเบเปƒเบ™เบชเบดเบšเป†เบ„เบปเบ™, เปเบ•เปˆเบ–เป‰เบฒเบกเบตเบซเบผเบฒเบเบเบงเปˆเบฒ 5 เบŠเบฑเป‰เบ™, เปเบฅเบฐเบกเบตเบฅเบนเบเบซเบฅเบฒเบ™เบซเบผเบฒเบเบชเบดเบšเบ„เบปเบ™, เบญเบฒเบ”เบˆเบฐเบกเบตเบšเบฑเบ™เบซเบฒ. เบ‚เปเปƒเบซเป‰เป€เบšเบดเปˆเบ‡เบงเบดเบ—เบตเบเบฒเบ™เบ„เบปเป‰เบ™เบซเบฒเปเบšเบšเบ”เบฑเป‰เบ‡เป€เบ”เบตเบกเบ‚เบญเบ‡เบ•เบปเบงเป€เบฅเบทเบญเบเบเบฒเบ™เบ„เบปเป‰เบ™เบซเบฒเปเบšเบšเบ”เบฑเป‰เบ‡เป€เบ”เบตเบกเบ–เบทเบเบ‚เบฝเบ™ (เปเบฅเบฐเป€เบฎเบฑเบ”เบงเบฝเบ). เปเบ•เปˆเบ—เปเบฒเบญเบดเบ”, เปƒเบซเป‰เบเปเบฒเบ™เบปเบ”เบงเปˆเบฒเบ‚เปเป‰เปƒเบ”เบˆเบฐเป€เบ›เบฑเบ™เบ—เบตเปˆเบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆเบซเบผเบฒเบเบ—เบตเปˆเบชเบธเบ”เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ„เบปเป‰เบ™เบ„เบงเป‰เบฒเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ.

เบชเปˆเบงเบ™เปƒเบซเบเปˆ "เป€เบฅเบดเบ" เบ•เบปเป‰เบ™เป„เบกเป‰เบเปˆเบญเบ:

WITH RECURSIVE T AS (
  SELECT
    id
  , pid
  , ARRAY[id] path
  FROM
    hier
  WHERE
    pid IS NULL
UNION ALL
  SELECT
    hier.id
  , hier.pid
  , T.path || hier.id
  FROM
    T
  JOIN
    hier
      ON hier.pid = T.id
)
TABLE T ORDER BY array_length(path, 1) DESC;

 id  | pid  | path
---------------------------------------------
7624 | 7623 | {7615,7620,7621,7622,7623,7624}
4995 | 4994 | {4983,4985,4988,4993,4994,4995}
4991 | 4990 | {4983,4985,4988,4989,4990,4991}
...

เบชเปˆเบงเบ™เปƒเบซเบเปˆ "เบเบงเป‰เบฒเบ‡" เบ•เบปเป‰เบ™เป„เบกเป‰เบเปˆเบญเบ:

...
SELECT
  path[1] id
, count(*)
FROM
  T
GROUP BY
  1
ORDER BY
  2 DESC;

id   | count
------------
5300 |   30
 450 |   28
1239 |   27
1573 |   25

เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เปƒเบŠเป‰เปเบšเบšเบ›เบปเบเบเบฐเบ•เบด เป€เบ‚เบปเป‰เบฒเบฎเปˆเบงเบก recursive:
PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™

เปเบ™เปˆเบ™เบญเบ™, เบ”เป‰เบงเบเบฎเบนเบšเปเบšเบšเบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเบ™เบตเป‰ เบˆเปเบฒเบ™เบงเบ™เบเบฒเบ™เบŠเปเป‰เบฒเบ„เบทเบ™เบˆเบฐเบเบปเบ‡เบเบฑเบšเบˆเปเบฒเบ™เบงเบ™เบฅเบนเบเบซเบฅเบฒเบ™เบ—เบฑเบ‡เปเบปเบ” (เปเบฅเบฐเบกเบตเบซเบผเบฒเบเบญเบฒเบเปเบเบฑเบชเบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒ), เปเบฅเบฐเบ™เบตเป‰เบชเบฒเบกเบฒเบ”เปƒเบŠเป‰เป€เบงเบฅเบฒเบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™, เปเบฅเบฐ, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เป€เบงเบฅเบฒ.

เปƒเบซเป‰เบเบงเบ”เป€เบšเบดเปˆเบ‡เบ•เบปเป‰เบ™เป„เบกเป‰เบเปˆเบญเบ "เบเบงเป‰เบฒเบ‡เบ—เบตเปˆเบชเบธเบ”":

WITH RECURSIVE T AS (
  SELECT
    id
  FROM
    hier
  WHERE
    id = 5300
UNION ALL
  SELECT
    hier.id
  FROM
    T
  JOIN
    hier
      ON hier.pid = T.id
)
TABLE T;

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™
[เป€เบšเบดเปˆเบ‡เบ—เบตเปˆเบญเบฐเบ—เบดเบšเบฒเบ.tensor.ru]

เบ”เบฑเปˆเบ‡เบ—เบตเปˆเบ„เบฒเบ”เป„เบงเป‰, เบžเบงเบเป€เบฎเบปเบฒเบžเบปเบšเป€เบซเบฑเบ™เบ—เบฑเบ‡เปเบปเบ” 30 เบšเบฑเบ™เบ—เบถเบ. เปเบ•เปˆเบžเบงเบเป€เบ‚เบปเบฒเปƒเบŠเป‰เป€เบงเบฅเบฒ 60% เบ‚เบญเบ‡เป€เบงเบฅเบฒเบ—เบฑเบ‡เบซเบกเบปเบ”เปƒเบ™เป€เบฅเบทเปˆเบญเบ‡เบ™เบตเป‰ - เป€เบžเบฒเบฐเบงเปˆเบฒเบžเบงเบเป€เบ‚เบปเบฒเบเบฑเบ‡เป€เบฎเบฑเบ” 30 เบ„เบปเป‰เบ™เบซเบฒเปƒเบ™เบ”เบฑเบ”เบชเบฐเบ™เบต. เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เบซเบ™เป‰เบญเบเบฅเบปเบ‡เบšเป?

เบเบงเบ”โ€‹เบชเบญเบšโ€‹เบซเบผเบฒเบโ€‹เป‚เบ”เบโ€‹เบ”เบฑเบ”โ€‹เบŠเบฐโ€‹เบ™เบตโ€‹

เบžเบงเบเป€เบฎเบปเบฒเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป€เบฎเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ”เบฑเบ”เบชเบฐเบ™เบตเปเบเบเบ•เปˆเบฒเบ‡เบซเบฒเบเบชเปเบฒเบฅเบฑเบšเปเบ•เปˆเบฅเบฐ node? เบกเบฑเบ™ turns เปƒเบซเป‰เป€เบซเบฑเบ™เบงเปˆเบฒเบšเปเปˆ - เบžเบงเบเป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เบญเปˆเบฒเบ™เบˆเบฒเบเบ”เบฑเบ”เบŠเบฐเบ™เบต เปƒเบŠเป‰เบเบฐเปเบˆเบซเบผเบฒเบเบญเบฑเบ™เบžเป‰เบญเบกเบเบฑเบ™เปƒเบ™เบชเบฒเบเบ”เบฝเบง เป‚เบ”เบเบเบฒเบ™เบŠเปˆเบงเบเป€เบซเบผเบทเบญ = ANY(array).

เปเบฅเบฐเปƒเบ™เปเบ•เปˆเบฅเบฐเบเบธเปˆเบกเบ•เบปเบงเบฅเบฐเบšเบธเบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเบžเบงเบเป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เป€เบญเบปเบฒ ID เบ—เบฑเบ‡เบซเบกเบปเบ”เบ—เบตเปˆเบžเบปเบšเปƒเบ™เบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ—เบตเปˆเบœเปˆเบฒเบ™เบกเบฒเป‚เบ”เบ "nodes". เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เปƒเบ™เปเบ•เปˆเบฅเบฐเบ‚เบฑเป‰เบ™เบ•เบญเบ™เบ•เปเปˆเป„เบ›เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐ เบŠเบญเบโ€‹เบซเบฒโ€‹เบฅเบนเบโ€‹เบซเบฅเบฒเบ™โ€‹เบ—เบฑเบ‡โ€‹เบซเบกเบปเบ”โ€‹เบ‚เบญเบ‡โ€‹เบฅเบฐโ€‹เบ”เบฑเบšโ€‹เปƒเบ”โ€‹เบซเบ™เบถเปˆเบ‡โ€‹เปƒเบ™โ€‹เป€เบงโ€‹เบฅเบฒโ€‹เบ”เบฝเบงโ€‹.

เบžเบฝเบ‡เปเบ•เปˆ, เบ™เบตเป‰เปเบกเปˆเบ™เบšเบฑเบ™เบซเบฒ, เปƒเบ™เบเบฒเบ™เบ„เบฑเบ”เป€เบฅเบทเบญเบ recursive, เบ—เปˆเบฒเบ™เบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบ•เบปเบงเบกเบฑเบ™เป€เบญเบ‡เปƒเบ™เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบ—เบตเปˆเบŠเป‰เบญเบ™เบเบฑเบ™, เปเบ•เปˆเบžเบงเบเป€เบฎเบปเบฒเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡ somehow เป€เบฅเบทเบญเบเบžเบฝเบ‡เปเบ•เปˆเบชเบดเปˆเบ‡เบ—เบตเปˆเบžเบปเบšเป€เบซเบฑเบ™เบขเบนเปˆเปƒเบ™เบฅเบฐเบ”เบฑเบšเบ—เบตเปˆเบœเปˆเบฒเบ™เบกเบฒ ... เบกเบฑเบ™ turns เปƒเบซเป‰เป€เบซเบฑเบ™เบงเปˆเบฒเบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เบšเปเปˆเป„เบ”เป‰เบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เบเบฒเบ™เบชเบญเบšเบ–เบฒเบก nested เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ„เบฑเบ”เป€เบฅเบทเบญเบเบ—เบฑเบ‡เบซเบกเบปเบ”, เปเบ•เปˆเบชเปเบฒเบฅเบฑเบšเบžเบฒเบเบชเบฐเบซเบ™เบฒเบกเบชเบฐเป€เบžเบฒเบฐเบ‚เบญเบ‡เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰. เปเบฅเบฐเบžเบฒเบเบชเบฐเบซเบ™เบฒเบกเบ™เบตเป‰เบเบฑเบ‡เบชเบฒเบกเบฒเบ”เป€เบ›เบฑเบ™ array - เป€เบŠเบดเปˆเบ‡เปเบกเปˆเบ™เบชเบดเปˆเบ‡เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบเบฒเบ™เปƒเบŠเป‰ ANY.

เบกเบฑเบ™เบŸเบฑเบ‡เบ„เบทเบšเป‰เบฒเป€เบฅเบฑเบเบ™เป‰เบญเบ, เปเบ•เปˆเปƒเบ™เปเบœเบ™เบงเบฒเบ”เบ—เบธเบเบขเปˆเบฒเบ‡เปเบกเปˆเบ™เบ‡เปˆเบฒเบเบ”เบฒเบ.

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™

WITH RECURSIVE T AS (
  SELECT
    ARRAY[id] id$
  FROM
    hier
  WHERE
    id = 5300
UNION ALL
  SELECT
    ARRAY(
      SELECT
        id
      FROM
        hier
      WHERE
        pid = ANY(T.id$)
    ) id$
  FROM
    T
  WHERE
    coalesce(id$, '{}') <> '{}' -- ัƒัะปะพะฒะธะต ะฒั‹ั…ะพะดะฐ ะธะท ั†ะธะบะปะฐ - ะฟัƒัั‚ะพะน ะผะฐััะธะฒ
)
SELECT
  unnest(id$) id
FROM
  T;

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™
[เป€เบšเบดเปˆเบ‡เบ—เบตเปˆเบญเบฐเบ—เบดเบšเบฒเบ.tensor.ru]

เปเบฅเบฐเปƒเบ™เบ—เบตเปˆเบ™เบตเป‰เบชเบดเปˆเบ‡เบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™เบ—เบตเปˆเบชเบธเบ”เบšเปเปˆเปเบกเปˆเบ™เปเบ•เปˆ เบŠเบฐเบ™เบฐ 1.5 เบ„เบฑเป‰เบ‡เปƒเบ™เป€เบงเบฅเบฒ, เปเบฅเบฐเบงเปˆเบฒเบžเบงเบเป€เบฎเบปเบฒเบฅเบปเบš buffers เบซเบ™เป‰เบญเบเบฅเบปเบ‡, เป€เบžเบฒเบฐเบงเปˆเบฒเบžเบงเบเป€เบฎเบปเบฒเบกเบตเบžเบฝเบ‡เปเบ•เปˆ 5 เป‚เบ—เป„เบ›เบซเบฒเบ”เบฑเบ”เบŠเบฐเบ™เบตเปเบ—เบ™เบ—เบตเปˆเบˆเบฐเป€เบ›เบฑเบ™ 30!

เป‚เบšเบ™เบฑเบ”เป€เบžเบตเปˆเบกเป€เบ•เบตเบกเปเบกเปˆเบ™เบ„เบงเบฒเบกเบˆเบดเบ‡เบ—เบตเปˆเบงเปˆเบฒเบซเบผเบฑเบ‡เบˆเบฒเบ unnest เบชเบธเบ”เบ—เป‰เบฒเบ, เบ•เบปเบงเบเปเบฒเบ™เบปเบ”เบˆเบฐเบเบฑเบ‡เบ„เบปเบ‡เบ„เปเบฒเบชเบฑเปˆเบ‡เป‚เบ”เบ "เบฅเบฐเบ”เบฑเบš".

เบ›เป‰เบฒเบ node

เบเบฒเบ™เบžเบดเบˆเบฒเบฅเบฐเบ™เบฒเบ•เปเปˆเป„เบ›เบ—เบตเปˆเบˆเบฐเบŠเปˆเบงเบเปƒเบซเป‰เบเบฒเบ™เบ›เบฑเบšเบ›เบธเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เปเบกเปˆเบ™ โˆ’ "เปƒเบš" เบšเปเปˆเบชเบฒเบกเบฒเบ”เบกเบตเบฅเบนเบเป„เบ”เป‰, เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เบชเปเบฒเบฅเบฑเบšเบžเบงเบเป€เบ‚เบปเบฒเบšเปเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป€เบšเบดเปˆเบ‡ "เบฅเบปเบ‡" เป€เบฅเบตเบ. เปƒเบ™เบเบฒเบ™เบเปเบฒเบ™เบปเบ”เบงเบฝเบเบ‡เบฒเบ™เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, เบ™เบตเป‰เบซเบกเบฒเบเบ„เบงเบฒเบกเบงเปˆเบฒเบ–เป‰เบฒเบžเบงเบเป€เบฎเบปเบฒเบ›เบฐเบ•เบดเบšเบฑเบ”เบ•เบฒเบกเบฅเบฐเบšเบปเบšเบ•เปˆเบญเบ‡เป‚เบชเป‰เบ‚เบญเบ‡เบžเบฐเปเบ™เบเบเบฒเบ™เปเบฅเบฐเบšเบฑเบ™เบฅเบธเบžเบฐเบ™เบฑเบเบ‡เบฒเบ™, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบšเปเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบŠเบญเบเบซเบฒเบชเบฒเบ‚เบฒเบ™เบตเป‰เบ•เบทเปˆเบกเบญเบตเบ.

เปƒเบซเป‰เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ เป€เบžเบตเปˆเบกเป€เบ•เบตเบก boolean- เบžเบฒเบเบชเบฐเบซเบ™เบฒเบก, เป€เบŠเบดเปˆเบ‡เบ—เบฑเบ™เบ—เบตเบˆเบฐเบšเบญเบเบžเบงเบเป€เบฎเบปเบฒเบงเปˆเบฒเบ™เบตเป‰เบชเบฐเป€เบžเบฒเบฐเบขเบนเปˆเปƒเบ™เบ•เบปเป‰เบ™เป„เบกเป‰เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเปเบกเปˆเบ™ "เบ‚เปเป‰" - เบ™เบฑเป‰เบ™เปเบกเปˆเบ™, เบšเปเปˆเบงเปˆเบฒเบˆเบฐเป€เบ›เบฑเบ™เบกเบฑเบ™เบชเบฒเบกเบฒเบ”เบกเบตเป€เบŠเบทเป‰เบญเบชเบฒเบเบ—เบฑเบ‡เบซเบกเบปเบ”.

ALTER TABLE hier
  ADD COLUMN branch boolean;

UPDATE
  hier T
SET
  branch = TRUE
WHERE
  EXISTS(
    SELECT
      NULL
    FROM
      hier
    WHERE
      pid = T.id
    LIMIT 1
);
-- ะ—ะฐะฟั€ะพั ัƒัะฟะตัˆะฝะพ ะฒั‹ะฟะพะปะฝะตะฝ: 3033 ัั‚ั€ะพะบ ะธะทะผะตะฝะตะฝะพ ะทะฐ 42 ะผั.

เบเบดเปˆเบ‡เปƒเบซเบเปˆ! เบกเบฑเบ™ turns เปƒเบซเป‰โ€‹เป€เบซเบฑเบ™โ€‹เบงเปˆเบฒโ€‹เบžเบฝเบ‡โ€‹เป€เบฅเบฑเบโ€‹เบ™เป‰เบญเบโ€‹เบซเบผเบฒเบโ€‹เบโ€‹เปˆโ€‹เบงเบฒ 30โ€‹% เบ‚เบญเบ‡โ€‹เบญเบปเบ‡โ€‹เบ›เบฐโ€‹เบเบญเบšโ€‹เบ‚เบญเบ‡โ€‹เบ•เบปเป‰เบ™โ€‹เป„เบกเป‰โ€‹เบ—เบฑเบ‡โ€‹เบซเบกเบปเบ”โ€‹เบกเบตโ€‹เบฅเบนเบโ€‹เบซเบฅเบฒเบ™โ€‹.

เบ•เบญเบ™เบ™เบตเป‰เปƒเบซเป‰เปƒเบŠเป‰เบเบปเบ™เป„เบเบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เป€เบฅเบฑเบเบ™เป‰เบญเบ - เบเบฒเบ™เป€เบŠเบทเปˆเบญเบกเบ•เปเปˆเบเบฑเบšเบžเบฒเบเบชเปˆเบงเบ™ recursive เบœเปˆเบฒเบ™ LATERAL, เป€เบŠเบดเปˆเบ‡เบˆเบฐเบŠเปˆเบงเบเปƒเบซเป‰เบžเบงเบเป€เบฎเบปเบฒเป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบ—เบปเปˆเบ‡เบ™เบฒเบ‚เบญเบ‡ "เบ•เบฒเบ•เบฐเบฅเบฒเบ‡" recursive เบ—เบฑเบ™เบ—เบต, เปเบฅเบฐเบ™เปเบฒเปƒเบŠเป‰เบซเบ™เป‰เบฒเบ—เบตเปˆเบฅเบงเบกเบ—เบตเปˆเบกเบตเป€เบ‡เบทเปˆเบญเบ™เป„เบ‚เบเบฒเบ™เบเบฑเปˆเบ™เบ•เบญเบ‡เป‚เบ”เบเบญเบตเบ‡เปƒเบชเปˆ node เป€เบžเบทเปˆเบญเบซเบผเบธเบ”เบœเปˆเบญเบ™เบŠเบธเบ”เบ‚เบญเบ‡เบ„เบต:

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™

WITH RECURSIVE T AS (
  SELECT
    array_agg(id) id$
  , array_agg(id) FILTER(WHERE branch) ns$
  FROM
    hier
  WHERE
    id = 5300
UNION ALL
  SELECT
    X.*
  FROM
    T
  JOIN LATERAL (
    SELECT
      array_agg(id) id$
    , array_agg(id) FILTER(WHERE branch) ns$
    FROM
      hier
    WHERE
      pid = ANY(T.ns$)
  ) X
    ON coalesce(T.ns$, '{}') <> '{}'
)
SELECT
  unnest(id$) id
FROM
  T;

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™
[เป€เบšเบดเปˆเบ‡เบ—เบตเปˆเบญเบฐเบ—เบดเบšเบฒเบ.tensor.ru]

เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹เบชเบฒโ€‹เบกเบฒเบ”โ€‹เบซเบผเบธเบ”โ€‹เบœเปˆเบญเบ™โ€‹เบเบฒเบ™โ€‹เป‚เบ—โ€‹เบ”เบฑเบ”โ€‹เบŠเบฐโ€‹เบ™เบตโ€‹เบญเบตเบโ€‹เบซเบ™เบถเปˆเบ‡โ€‹เปเบฅเบฐโ€‹ เบŠเบฐเบ™เบฐเบซเบผเบฒเบเบเบงเปˆเบฒ 2 เบ„เบฑเป‰เบ‡เปƒเบ™เบ›เบฐเบฅเบดเบกเบฒเบ™ เบžเบดเบชเบนเบ”.

#2. เปƒเบซเป‰เบเบฑเบšเบ„เบทเบ™เป„เบ›เบซเบฒเบฎเบฒเบ

เบชเบนเบ”เบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆเบ™เบตเป‰เบˆเบฐเป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”เบ–เป‰เบฒเบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เบเบฒเบ™เป€เบเบฑเบšเบเปเบฒเบ‚เปเป‰เบกเบนเบ™เบชเปเบฒเบฅเบฑเบšเบญเบปเบ‡เบ›เบฐเบเบญเบšเบ—เบฑเบ‡เบซเบกเบปเบ” "เบ‚เบถเป‰เบ™เบ•เบปเป‰เบ™เป„เบกเป‰", เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆเป€เบเบฑเบšเบฎเบฑเบเบชเบฒเบ‚เปเป‰เบกเบนเบ™เบเปˆเบฝเบงเบเบฑเบšเป€เบญเบเบฐเบชเบฒเบ™เปเบซเบผเปˆเบ‡เปƒเบ” (เปเบฅเบฐเบกเบตเบ•เบปเบงเบŠเบตเป‰เบงเบฑเบ”เบญเบฑเบ™เปƒเบ”) เบ—เบตเปˆเป€เบฎเบฑเบ”เปƒเบซเป‰เบกเบฑเบ™เบ–เบทเบเบฅเบงเบกเป€เบ‚เบปเป‰เบฒเปƒเบ™เบ•เบปเบงเบขเปˆเบฒเบ‡ - เบ•เบปเบงเบขเปˆเบฒเบ‡, เบเบฒเบ™เบชเป‰เบฒเบ‡เบšเบปเบ”เบฅเบฒเบเบ‡เบฒเบ™เบชเบฐเบซเบผเบธเบš. เบ”เป‰เบงเบเบเบฒเบ™เบฅเบงเบšเบฅเบงเบกเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™ nodes.

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™
เบชเบดเปˆเบ‡เบ—เบตเปˆเบ•เปเปˆเป„เบ›เบ™เบตเป‰เบ„เบงเบ™เบˆเบฐเบ–เบทเบเบ›เบฐเบ•เบดเบšเบฑเบ”เบžเบฝเบ‡เปเบ•เปˆเป€เบ›เบฑเบ™เบซเบผเบฑเบเบ–เบฒเบ™เบชเบฐเปเบ”เบ‡เปเบ™เบงเบ„เบงเบฒเบกเบ„เบดเบ”, เบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเป„เบ”เป‰เบเบฒเบเป€เบ›เบฑเบ™เป€เบฅเบทเปˆเบญเบ‡เบ—เบตเปˆเบซเบเบธเป‰เบ‡เบเบฒเบเบซเบผเบฒเบ. เปเบ•เปˆเบ–เป‰เบฒเบกเบฑเบ™เบ„เบญเบšเบ‡เปเบฒเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ‚เบญเบ‡เป€เบˆเบปเป‰เบฒ, เบ—เปˆเบฒเบ™เบ„เบงเบ™เบ„เบดเบ”เบเปˆเบฝเบงเบเบฑเบšเบเบฒเบ™เปƒเบŠเป‰เป€เบ•เบฑเบเบ™เบดเบเบ—เบตเปˆเบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™.

เปƒเบซเป‰เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ”เป‰เบงเบเบชเบญเบ‡เบชเบฒเบกเบ„เปเบฒเบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบ:

  • เบšเบฑเบ™เบ—เบถเบเบ”เบฝเบงเบเบฑเบ™เบˆเบฒเบเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™ เบกเบฑเบ™เบ”เบตเบ—เบตเปˆเบชเบธเบ”เบ—เบตเปˆเบˆเบฐเบญเปˆเบฒเบ™เบกเบฑเบ™เป€เบ—เบทเปˆเบญเบ”เบฝเบง.
  • เบšเบฑเบ™เบ—เบถเบเบˆเบฒเบเบ–เบฒเบ™เบ‚เปเป‰เบกเบนเบ™ เบกเบฑเบ™เบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบซเบผเบฒเบเปƒเบ™เบเบฒเบ™เบญเปˆเบฒเบ™เป€เบ›เบฑเบ™เบŠเบธเบ”เบเบงเปˆเบฒเบ„เบปเบ™เบ”เบฝเบง.

เบ•เบญเบ™เบ™เบตเป‰เปƒเบซเป‰เบžเบฐเบเบฒเบเบฒเบกเบชเป‰เบฒเบ‡เบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เปเบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบเบฒเบ™.

เบ‚เบฑเป‰เบ™เบ•เบญเบ™ 1

เปเบ™เปˆเบ™เบญเบ™, เป€เบกเบทเปˆเบญเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™ recursion (เบšเปˆเบญเบ™เบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบšเปเปˆเบกเบตเบกเบฑเบ™!) เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ•เป‰เบญเบ‡เบฅเบปเบšเบšเบฑเบ™เบ—เบถเบเบ‚เบญเบ‡เปƒเบšเบ”เป‰เบงเบเบ•เบปเบ™เป€เบญเบ‡เป‚เบ”เบเบญเบตเบ‡เปƒเบชเปˆเบŠเบธเบ”เบ‚เบญเบ‡เบ•เบปเบงเบฅเบฐเบšเบธเป€เบšเบทเป‰เบญเบ‡เบ•เบปเป‰เบ™:

WITH RECURSIVE tree AS (
  SELECT
    rec -- ัั‚ะพ ั†ะตะปัŒะฝะฐั ะทะฐะฟะธััŒ ั‚ะฐะฑะปะธั†ั‹
  , id::text chld -- ัั‚ะพ "ะฝะฐะฑะพั€" ะฟั€ะธะฒะตะดัˆะธั… ััŽะดะฐ ะธัั…ะพะดะฝั‹ั… ะปะธัั‚ัŒะตะฒ
  FROM
    hier rec
  WHERE
    id = ANY('{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192}'::integer[])
UNION ALL
  ...

เบ–เป‰เบฒเบกเบฑเบ™เป€เบšเบดเปˆเบ‡เบ„เบทเบงเปˆเบฒเปเบ›เบเบ›เบฐเบซเบฅเบฒเบ”เบเบฑเบšเบœเบนเป‰เปƒเบ”เบœเบนเป‰เบ™เบถเปˆเบ‡เบ—เบตเปˆ "เบŠเบธเบ”" เบ–เบทเบเป€เบเบฑเบšเป„เบงเป‰เป€เบ›เบฑเบ™เบชเบฐเบ•เบฃเบดเบ‡เปเบฅเบฐเบšเปเปˆเปเบกเปˆเบ™ array, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบกเบตเบ„เปเบฒเบญเบฐเบ—เบดเบšเบฒเบเบ‡เปˆเบฒเบเป†เบชเปเบฒเบฅเบฑเบšเป€เบฅเบทเปˆเบญเบ‡เบ™เบตเป‰. เบกเบตเบŸเบฑเบ‡เบŠเบฑเบ™ "gluing" เบ›เบฐเบชเบปเบกเบ›เบฐเบชเบฒเบ™เปƒเบ™เบ•เบปเบงเบชเปเบฒเบฅเบฑเบšเบชเบฒเบ string_agg, เปเบ•เปˆเบšเปเปˆเปเบกเปˆเบ™เบชเปเบฒเบฅเบฑเบš arrays. เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบ™เบฒเบ‡ เบ‡เปˆเบฒเบโ€‹เบ—เบตเปˆโ€‹เบˆเบฐโ€‹เบ›เบฐโ€‹เบ•เบดโ€‹เบšเบฑเบ”โ€‹เบ”เป‰เบงเบโ€‹เบ•เบปเบ™โ€‹เป€เบญเบ‡โ€‹.

เบ‚เบฑเป‰เบ™เบ•เบญเบ™ 2

เบ•เบญเบ™เบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเป„เบ”เป‰เบฎเบฑเบšเบŠเบธเบ” ID เบžเบฒเบเบชเปˆเบงเบ™เบ—เบตเปˆเบˆเบฐเบ•เป‰เบญเบ‡เบญเปˆเบฒเบ™เบ•เบทเปˆเบกเบญเบตเบ. เป€เบเบทเบญเบšเบชเบฐเป€เบซเบกเบตเบžเบงเบเป€เบ‚เบปเบฒเบˆเบฐเบ–เบทเบเบŠเป‰เปเบฒเบเบฑเบ™เปƒเบ™เบšเบฑเบ™เบ—เบถเบเบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เบ‚เบญเบ‡เบŠเบธเบ”เบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบš - เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐ เบˆเบฑเบ”เบเบธเปˆเบกเปƒเบซเป‰เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒ, เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆเบฎเบฑเบเบชเบฒเบ‚เปเป‰เบกเบนเบ™เบเปˆเบฝเบงเบเบฑเบšเปƒเบšเปเบซเบผเปˆเบ‡.

เปเบ•เปˆเบ™เบตเป‰เบชเบฒเบกเบšเบฑเบ™เบซเบฒเบฅเปเบ–เป‰เบฒเบžเบงเบเป€เบฎเบปเบฒ:

  1. เบžเบฒเบเบชเปˆเบงเบ™ "subrecursive" เบ‚เบญเบ‡เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบšเปเปˆเบชเบฒเบกเบฒเบ”เบกเบตเบซเบ™เป‰เบฒเบ—เบตเปˆเบฅเบงเบกเบเบฑเบš GROUP BY.
  2. เบเบฒเบ™เบญเป‰เบฒเบ‡เบญเบตเบ‡เป€เบ–เบดเบ‡ "เบ•เบฒเบ•เบฐเบฅเบฒเบ‡" recursive เบšเปเปˆเบชเบฒเบกเบฒเบ”เบขเบนเปˆเปƒเบ™ subquery เบŠเป‰เบญเบ™.
  3. เบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเบขเบนเปˆเปƒเบ™เบžเบฒเบเบชเปˆเบงเบ™ recursive เบšเปเปˆเบชเบฒเบกเบฒเบ”เบกเบต CTE เป„เบ”เป‰.

เป‚เบŠเบเบ”เบต, เบšเบฑเบ™เบซเบฒเบ—เบฑเบ‡เบซเบกเบปเบ”เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰เปเบกเปˆเบ™เบ‚เป‰เบญเบ™เบ‚เป‰เบฒเบ‡เบ‡เปˆเบฒเบเบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เบงเบฝเบเบ›เบฐเบกเบฒเบ™. เปƒเบซเป‰เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบˆเบฒเบเบ—เบตเปˆเบชเบธเบ”.

CTE เปƒเบ™เบชเปˆเบงเบ™ recursive

เบ™เบตเป‰เบ„เบทเบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™ เบšเปเปˆ เป€เบฎเบฑเบ”เบงเบฝเบ:

WITH RECURSIVE tree AS (
  ...
UNION ALL
  WITH T (...)
  SELECT ...
)

เปเบฅเบฐเบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบกเบฑเบ™เป€เบฎเบฑเบ”เบงเบฝเบ, เบงเบปเบ‡เป€เบฅเบฑเบšเป€เบฎเบฑเบ”เปƒเบซเป‰เบ„เบงเบฒเบกเปเบ•เบเบ•เปˆเบฒเบ‡!

WITH RECURSIVE tree AS (
  ...
UNION ALL
  (
    WITH T (...)
    SELECT ...
  )
)

Nested query เบ•เปเปˆเบเบฑเบš "เบ•เบฒเบ•เบฐเบฅเบฒเบ‡" recursive

Hmm... CTE recursive เบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เป„เบ”เป‰เปƒเบ™เบเบฒเบ™เบชเบญเบšเบ–เบฒเบกเบเปˆเบญเบ. เปเบ•เปˆเบกเบฑเบ™เบญเบฒเบ”เบˆเบฐเบขเบนเปˆเปƒเบ™ CTE! เปเบฅเบฐเบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเบ—เบตเปˆเบŠเป‰เบญเบ™เบเบฑเบ™เบชเบฒเบกเบฒเบ”เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡ CTE เบ™เบตเป‰เปเบฅเป‰เบง!

GROUP BY เบžเบฒเบเปƒเบ™ recursion

เบกเบฑเบ™เบšเปเปˆเป€เบ›เบฑเบ™เบ—เบตเปˆเบžเปเปƒเบˆ, เปเบ•เปˆ... เบžเบงเบเป€เบฎเบปเบฒเบกเบตเบงเบดเบ—เบตเบ‡เปˆเบฒเบเป†เบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เบ•เบฒเบกเปเบšเบšเบเบธเปˆเบกเป‚เบ”เบเบเบฒเบ™เปƒเบŠเป‰ DISTINCT ON เปเบฅเบฐโ€‹เบซเบ™เป‰เบฒโ€‹เบ•เปˆเบฒเบ‡โ€‹เบซเบ™เป‰เบฒโ€‹เบ•เปˆเบฒเบ‡โ€‹!

SELECT
  (rec).pid id
, string_agg(chld::text, ',') chld
FROM
  tree
WHERE
  (rec).pid IS NOT NULL
GROUP BY 1 -- ะฝะต ั€ะฐะฑะพั‚ะฐะตั‚!

เปเบฅเบฐเบ™เบตเป‰เปเบกเปˆเบ™เบงเบดเบ—เบตเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบ!

SELECT DISTINCT ON((rec).pid)
  (rec).pid id
, string_agg(chld::text, ',') OVER(PARTITION BY (rec).pid) chld
FROM
  tree
WHERE
  (rec).pid IS NOT NULL

เบ”เบฝเบงเบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเป€เบซเบฑเบ™เบงเปˆเบฒเป€เบ›เบฑเบ™เบซเบเบฑเบ‡ ID เบ•เบปเบงเป€เบฅเบเบˆเบถเปˆเบ‡เบ–เบทเบเบ›เปˆเบฝเบ™เป€เบ›เบฑเบ™เบ‚เปเป‰เบ„เบงเบฒเบก - เป€เบžเบทเปˆเบญเปƒเบซเป‰เบžเบงเบเป€เบ‚เบปเบฒเป€เบ‚เบปเป‰เบฒเบเบฑเบ™เป„เบ”เป‰เป‚เบ”เบเปเบเบเบ”เป‰เบงเบเป€เบ„เบทเปˆเบญเบ‡เปเบฒเบเบˆเบธเบ”!

เบ‚เบฑเป‰เบ™เบ•เบญเบ™ 3

เบชเปเบฒเบฅเบฑเบšเบชเบธเบ”เบ—เป‰เบฒเบเบžเบงเบเป€เบฎเบปเบฒเบšเปเปˆเบกเบตเบซเบเบฑเบ‡เป€เบซเบผเบทเบญ:

  • เบžเบงเบเป€เบฎเบปเบฒเบญเปˆเบฒเบ™ "เบžเบฒเบเบชเปˆเบงเบ™" เบšเบฑเบ™เบ—เบถเบเป‚เบ”เบเบญเบตเบ‡เปƒเบชเปˆเบŠเบธเบ”เบ‚เบญเบ‡ IDs เบเบธเปˆเบก
  • เบžเบงเบเป€เบฎเบปเบฒเบชเบปเบกเบ—เบฝเบšเบชเปˆเบงเบ™เบ—เบตเปˆเบ–เบทเบเบฅเบปเบšเบเบฑเบš "เบŠเบธเบ”" เบ‚เบญเบ‡เปเบœเปˆเบ™เบ•เบปเป‰เบ™เบชเบฐเบšเบฑเบš
  • "เบ‚เบฐเบซเบเบฒเบ" เปเบ–เบšเบ—เบตเปˆเบเปเบฒเบ™เบปเบ”เป„เบงเป‰เป‚เบ”เบเปƒเบŠเป‰ unnest(string_to_array(chld, ',')::integer[])

WITH RECURSIVE tree AS (
  SELECT
    rec
  , id::text chld
  FROM
    hier rec
  WHERE
    id = ANY('{1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192}'::integer[])
UNION ALL
  (
    WITH prnt AS (
      SELECT DISTINCT ON((rec).pid)
        (rec).pid id
      , string_agg(chld::text, ',') OVER(PARTITION BY (rec).pid) chld
      FROM
        tree
      WHERE
        (rec).pid IS NOT NULL
    )
    , nodes AS (
      SELECT
        rec
      FROM
        hier rec
      WHERE
        id = ANY(ARRAY(
          SELECT
            id
          FROM
            prnt
        ))
    )
    SELECT
      nodes.rec
    , prnt.chld
    FROM
      prnt
    JOIN
      nodes
        ON (nodes.rec).id = prnt.id
  )
)
SELECT
  unnest(string_to_array(chld, ',')::integer[]) leaf
, (rec).*
FROM
  tree;

PostgreSQL Antipatterns: เบ‚เบธเบกเบเบฐเบ•เปˆเบฒเบเป€เบฅเบดเบเป€เบ—เบปเปˆเบฒเปƒเบ”? เปƒเบซเป‰เป„เบ›เป‚เบ”เบเบœเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบŠเบฑเป‰เบ™
[เป€เบšเบดเปˆเบ‡เบ—เบตเปˆเบญเบฐเบ—เบดเบšเบฒเบ.tensor.ru]

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™