PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: เจ†เจ‰ เจ‡เฉฑเจ• เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจฆเฉ‡ เจจเจพเจฒ เจญเจพเจฐเฉ€ เจœเฉเจ†เจ‡เจจ เจ•เจฐเฉ€เจ

เจ…เจธเฉ€เจ‚ "เจชเฉเจฐเจคเฉ€เจค เจคเฉŒเจฐ 'เจคเฉ‡ เจธเจงเจพเจฐเจจ" PostgreSQL เจธเจตเจพเจฒเจพเจ‚ เจฆเฉ‡ เจชเฉเจฐเจฆเจฐเจธเจผเจจ เจจเฉ‚เฉฐ เจฌเจฟเจนเจคเจฐ เจฌเจฃเจพเจ‰เจฃ เจฒเจˆ เจฌเจนเฉเจค เจ˜เฉฑเจŸ เจœเจพเจฃเฉ‡-เจชเจ›เจพเจฃเฉ‡ เจคเจฐเฉ€เจ•เจฟเจ†เจ‚ เจฆเฉ‡ เจ…เจงเจฟเจเจจ เจฒเจˆ เจธเจฎเจฐเจชเจฟเจค เจฒเฉ‡เจ–เจพเจ‚ เจฆเฉ€ เจฒเฉœเฉ€ เจจเฉ‚เฉฐ เจœเจพเจฐเฉ€ เจฐเฉฑเจ–เจฆเฉ‡ เจนเจพเจ‚:

เจ‡เจน เจจเจพ เจธเฉ‹เจšเฉ‹ เจ•เจฟ เจฎเฉˆเจจเฉ‚เฉฐ เจธเจผเจพเจฎเจฒ เจนเฉ‹เจฃเจพ เจฌเจนเฉเจค เจชเจธเฉฐเจฆ เจจเจนเฉ€เจ‚ เจนเฉˆ... :)

เจชเจฐ เจ…เจ•เจธเจฐ เจ‡เจธเจฆเฉ‡ เจฌเจฟเจจเจพเจ‚, เจฌเฉ‡เจจเจคเฉ€ เจ‡เจธเจฆเฉ‡ เจจเจพเจฒ เจจเจพเจฒเฉ‹เจ‚ เจ•เจพเจซเจผเฉ€ เจœเจผเจฟเจ†เจฆเจพ เจฒเจพเจญเจ•เจพเจฐเฉ€ เจธเจพเจฌเจค เจนเฉเฉฐเจฆเฉ€ เจนเฉˆ. เจ‡เจธ เจฒเจˆ เจ…เฉฑเจœ เจ…เจธเฉ€เจ‚ เจ•เฉ‹เจธเจผเจฟเจธเจผ เจ•เจฐเจพเจ‚เจ—เฉ‡ เจธเจฐเฉ‹เจค-เจธเฉฐเจฌเฉฐเจงเฉ€ เจธเจผเจพเจฎเจฒ เจนเฉ‹เจฃ เจคเฉ‹เจ‚ เจ›เฉเจŸเจ•เจพเจฐเจพ เจชเจพเจ“ - เจ‡เฉฑเจ• เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ.

PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: เจ†เจ‰ เจ‡เฉฑเจ• เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจฆเฉ‡ เจจเจพเจฒ เจญเจพเจฐเฉ€ เจœเฉเจ†เจ‡เจจ เจ•เจฐเฉ€เจ

PostgreSQL 12 เจจเจพเจฒ เจธเจผเฉเจฐเฉ‚ เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ, เจนเฉ‡เจ เจพเจ‚ เจฆเฉฑเจธเฉ€เจ†เจ‚ เจ—เจˆเจ†เจ‚ เจ•เฉเจ เจธเจฅเจฟเจคเฉ€เจ†เจ‚ เจฆเฉ‡ เจ•เจพเจฐเจจ เจฅเฉ‹เฉœเฉเจนเฉ‡ เจตเฉฑเจ–เจฐเฉ‡ เจคเฉŒเจฐ 'เจคเฉ‡ เจฆเฉเจฌเจพเจฐเจพ เจคเจฟเจ†เจฐ เจ•เฉ€เจคเจพ เจœเจพ เจธเจ•เจฆเจพ เจนเฉˆ เจกเจฟเจซเจพเจฒเจŸ เจ—เฉˆเจฐ-เจชเจฆเจพเจฐเจฅเฉ€เจ•เจฐเจจ CTE. เจ‡เจธ เจตเจฟเจตเจนเจพเจฐ เจจเฉ‚เฉฐ เจ•เฉเฉฐเจœเฉ€ เจฆเฉ‡ เจ•เฉ‡ เจตเจพเจชเจธ เจฒเจฟเจ† เจœเจพ เจธเจ•เจฆเจพ เจนเฉˆ MATERIALIZED.

เจ‡เฉฑเจ• เจธเฉ€เจฎเจค เจธเจผเจฌเจฆเจพเจตเจฒเฉ€ เจตเจฟเฉฑเจš เจฌเจนเฉเจค เจธเจพเจฐเฉ‡ "เจคเฉฑเจฅ"

เจšเจฒเฉ‹ เจ‡เฉฑเจ• เจฌเจนเฉเจค เจนเฉ€ เจ…เจธเจฒ เจเจชเจฒเฉ€เจ•เฉ‡เจธเจผเจจ เจŸเจพเจธเจ• เจฒเฉˆเจ‚เจฆเฉ‡ เจนเจพเจ‚ - เจธเจพเจจเฉ‚เฉฐ เจ‡เฉฑเจ• เจธเฉ‚เจšเฉ€ เจชเฉเจฐเจฆเจฐเจธเจผเจฟเจค เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ เจ†เจ‰เจฃ เจตเจพเจฒเฉ‡ เจธเฉเจจเฉ‡เจนเฉ‡ เจœเจพเจ‚ เจญเฉ‡เจœเจฃ เจตเจพเจฒเจฟเจ†เจ‚ เจจเจพเจฒ เจธเจฐเจ—เจฐเจฎ เจ•เฉฐเจฎ:

25.01 | ะ˜ะฒะฐะฝะพะฒ ะ˜.ะ˜. | ะŸะพะดะณะพั‚ะพะฒะธั‚ัŒ ะพะฟะธัะฐะฝะธะต ะฝะพะฒะพะณะพ ะฐะปะณะพั€ะธั‚ะผะฐ.
22.01 | ะ˜ะฒะฐะฝะพะฒ ะ˜.ะ˜. | ะะฐะฟะธัะฐั‚ัŒ ัั‚ะฐั‚ัŒัŽ ะฝะฐ ะฅะฐะฑั€: ะถะธะทะฝัŒ ะฑะตะท JOIN.
20.01 | ะŸะตั‚ั€ะพะฒ ะŸ.ะŸ. | ะŸะพะผะพั‡ัŒ ะพะฟั‚ะธะผะธะทะธั€ะพะฒะฐั‚ัŒ ะทะฐะฟั€ะพั.
18.01 | ะ˜ะฒะฐะฝะพะฒ ะ˜.ะ˜. | ะะฐะฟะธัะฐั‚ัŒ ัั‚ะฐั‚ัŒัŽ ะฝะฐ ะฅะฐะฑั€: JOIN ั ัƒั‡ะตั‚ะพะผ ั€ะฐัะฟั€ะตะดะตะปะตะฝะธั ะดะฐะฝะฝั‹ั….
16.01 | ะŸะตั‚ั€ะพะฒ ะŸ.ะŸ. | ะŸะพะผะพั‡ัŒ ะพะฟั‚ะธะผะธะทะธั€ะพะฒะฐั‚ัŒ ะทะฐะฟั€ะพั.

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

เจ†เจ“ เจธเจตเฉ€เจ•เจพเจฐ เจ•เจฐเฉ€เจ เจ•เจฟ 1000 เจฒเฉ‹เจ•เจพเจ‚ เจฆเฉ€ เจธเจพเจกเฉ€ เจธเฉฐเจธเจฅเจพ เจตเจฟเฉฑเจš, เจธเจฟเจฐเจซ 20 เจฒเฉ‡เจ–เจ• (เจ†เจฎ เจคเฉŒเจฐ 'เจคเฉ‡ เจ‡เจธ เจคเฉ‹เจ‚ เจตเฉ€ เจ˜เฉฑเจŸ) เจนเจฐเฉ‡เจ• เจ–เจพเจธ เจ•เจฒเจพเจ•เจพเจฐ เจฒเจˆ เจ•เฉฐเจฎ เจจเจฟเจฐเจงเจพเจฐเจค เจ•เจฐเจฆเฉ‡ เจนเจจ เจ…เจคเฉ‡ เจ†เจ“ เจ‡เจธ เจตเจฟเจธเจผเฉ‡ เจฆเฉ‡ เจ—เจฟเจ†เจจ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเฉ€เจ"เจฐเจตเจพเจ‡เจคเฉ€" เจชเฉเฉฑเจ›เจ—เจฟเฉฑเจ› เจจเฉ‚เฉฐ เจคเฉ‡เจœเจผ เจ•เจฐเจจ เจฒเจˆเฅค

เจธเจ•เฉเจฐเจฟเจชเจŸ เจœเจจเจฐเฉ‡เจŸเจฐ

-- ัะพั‚ั€ัƒะดะฝะธะบะธ
CREATE TABLE person AS
SELECT
  id
, repeat(chr(ascii('a') + (id % 26)), (id % 32) + 1) "name"
, '2000-01-01'::date - (random() * 1e4)::integer birth_date
FROM
  generate_series(1, 1000) id;

ALTER TABLE person ADD PRIMARY KEY(id);

-- ะทะฐะดะฐั‡ะธ ั ัƒะบะฐะทะฐะฝะฝั‹ะผ ั€ะฐัะฟั€ะตะดะตะปะตะฝะธะตะผ
CREATE TABLE task AS
WITH aid AS (
  SELECT
    id
  , array_agg((random() * 999)::integer + 1) aids
  FROM
    generate_series(1, 1000) id
  , generate_series(1, 20)
  GROUP BY
    1
)
SELECT
  *
FROM
  (
    SELECT
      id
    , '2020-01-01'::date - (random() * 1e3)::integer task_date
    , (random() * 999)::integer + 1 owner_id
    FROM
      generate_series(1, 100000) id
  ) T
, LATERAL(
    SELECT
      aids[(random() * (array_length(aids, 1) - 1))::integer + 1] author_id
    FROM
      aid
    WHERE
      id = T.owner_id
    LIMIT 1
  ) a;

ALTER TABLE task ADD PRIMARY KEY(id);
CREATE INDEX ON task(owner_id, task_date);
CREATE INDEX ON task(author_id);

เจ†เจ‰ เจ‡เฉฑเจ• เจ–เจพเจธ เจเจ—เจœเจผเฉ€เจ•เจฟเจŠเจŸเจฐ เจฒเจˆ เจ†เจ–เจฐเฉ€ 100 เจ•เจพเจฐเจœ เจฆเจฟเจ–เจพเจ‰เจ‚เจฆเฉ‡ เจนเจพเจ‚:

SELECT
  task.*
, person.name
FROM
  task
LEFT JOIN
  person
    ON person.id = task.author_id
WHERE
  owner_id = 777
ORDER BY
  task_date DESC
LIMIT 100;

PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: เจ†เจ‰ เจ‡เฉฑเจ• เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจฆเฉ‡ เจจเจพเจฒ เจญเจพเจฐเฉ€ เจœเฉเจ†เจ‡เจจ เจ•เจฐเฉ€เจ
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจ‡เจน เจชเจคเจพ เจšเจฒเจฆเจพ เจนเฉˆ เจ•เจฟ 1/3 เจ•เฉเฉฑเจฒ เจธเจฎเจพเจ‚ เจ…เจคเฉ‡ 3/4 เจฐเฉ€เจกเจฟเฉฐเจ— เจกเฉ‡เจŸเจพ เจฆเฉ‡ เจชเฉฐเจจเจฟเจ†เจ‚ เจจเฉ‚เฉฐ เจฒเฉ‡เจ–เจ• เจฆเฉ€ เจ–เฉ‹เจœ เจ•เจฐเจจ เจฒเจˆ 100 เจตเจพเจฐ เจฌเจฃเจพเจ‡เจ† เจ—เจฟเจ† เจธเฉ€ - เจนเจฐเฉ‡เจ• เจ†เจ‰เจŸเจชเฉเฉฑเจŸ เจ•เจพเจฐเจœ เจฒเจˆเฅค เจชเจฐ เจ…เจธเฉ€เจ‚ เจœเจพเจฃเจฆเฉ‡ เจนเจพเจ‚ เจ•เจฟ เจ‡เจนเจจเจพเจ‚ เจธเฉˆเจ‚เจ•เฉœเฉ‡ เจตเจฟเฉฑเจšเฉ‹เจ‚ เจธเจฟเจฐเจซ 20 เจตเฉฑเจ–เจฐเฉ‡ - เจ•เฉ€ เจ‡เจธ เจ—เจฟเจ†เจจ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจจเจพ เจธเฉฐเจญเจต เจนเฉˆ?

hstore-เจ•เฉ‹เจธเจผ

เจ†เจ“ เจฒเจพเจญ เจ‰เจ เจพเจˆเจ hstore เจ•เจฟเจธเจฎ เจ‡เฉฑเจ• "เจกเจ•เจธเจผเจจเจฐเฉ€" เจ•เฉเฉฐเจœเฉ€-เจฎเฉเฉฑเจฒ เจฌเจฃเจพเจ‰เจฃ เจฒเจˆ:

CREATE EXTENSION hstore

เจธเจพเจจเฉ‚เฉฐ เจฒเฉ‡เจ–เจ• เจฆเฉ€ ID เจ…เจคเฉ‡ เจ‰เจธเจฆเจพ เจจเจพเจฎ เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจตเจฟเฉฑเจš เจชเจพเจ‰เจฃ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ เจคเจพเจ‚ เจœเฉ‹ เจ…เจธเฉ€เจ‚ เจซเจฟเจฐ เจ‡เจธ เจ•เฉเฉฐเจœเฉ€ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจ•เฉ‡ เจเจ•เจธเจŸเจฐเฉˆเจ•เจŸ เจ•เจฐ เจธเจ•เฉ€เจ:

-- ั„ะพั€ะผะธั€ัƒะตะผ ั†ะตะปะตะฒัƒัŽ ะฒั‹ะฑะพั€ะบัƒ
WITH T AS (
  SELECT
    *
  FROM
    task
  WHERE
    owner_id = 777
  ORDER BY
    task_date DESC
  LIMIT 100
)
-- ั„ะพั€ะผะธั€ัƒะตะผ ัะปะพะฒะฐั€ัŒ ะดะปั ัƒะฝะธะบะฐะปัŒะฝั‹ั… ะทะฝะฐั‡ะตะฝะธะน
, dict AS (
  SELECT
    hstore( -- hstore(keys::text[], values::text[])
      array_agg(id)::text[]
    , array_agg(name)::text[]
    )
  FROM
    person
  WHERE
    id = ANY(ARRAY(
      SELECT DISTINCT
        author_id
      FROM
        T
    ))
)
-- ะฟะพะปัƒั‡ะฐะตะผ ัะฒัะทะฐะฝะฝั‹ะต ะทะฝะฐั‡ะตะฝะธั ัะปะพะฒะฐั€ั
SELECT
  *
, (TABLE dict) -> author_id::text -- hstore -> key
FROM
  T;

PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: เจ†เจ‰ เจ‡เฉฑเจ• เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจฆเฉ‡ เจจเจพเจฒ เจญเจพเจฐเฉ€ เจœเฉเจ†เจ‡เจจ เจ•เจฐเฉ€เจ
[explanation.tensor.ru 'เจคเฉ‡ เจฆเฉ‡เจ–เฉ‹]

เจตเจฟเจ…เจ•เจคเฉ€เจ†เจ‚ เจฌเจพเจฐเฉ‡ เจœเจพเจฃเจ•เจพเจฐเฉ€ เจชเฉเจฐเจพเจชเจค เจ•เจฐเจจ 'เจคเฉ‡ เจ–เจฐเจš เจ•เฉ€เจคเจพ เจ—เจฟเจ† 2 เจ—เฉเจฃเจพ เจ˜เฉฑเจŸ เจธเจฎเจพเจ‚ เจ…เจคเฉ‡ 7 เจ—เฉเจฃเจพ เจ˜เฉฑเจŸ เจกเจพเจŸเจพ เจชเฉœเฉเจนเจฟเจ† เจœเจพเจ‚เจฆเจพ เจนเฉˆ! "เจธเจผเจฌเจฆเจพเจตเจฒเฉ€" เจคเฉ‹เจ‚ เจ‡เจฒเจพเจตเจพ, เจ‡เจนเจจเจพเจ‚ เจจเจคเฉ€เจœเจฟเจ†เจ‚ เจจเฉ‚เฉฐ เจชเฉเจฐเจพเจชเจค เจ•เจฐเจจ เจตเจฟเฉฑเจš เจธเจพเจกเฉ€ เจฎเจฆเจฆ เจ•เฉ€เจคเฉ€ เจฌเจฒเจ• เจฐเจฟเจ•เจพเจฐเจก เจฎเฉเฉœ เจชเฉเจฐเจพเจชเจคเฉ€ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจฆเฉ‡ เจนเฉ‹เจ เจ‡เฉฑเจ• เจธเจฟเฉฐเจ—เจฒ เจชเจพเจธ เจตเจฟเฉฑเจš เจŸเฉ‡เจฌเจฒ เจคเฉ‹เจ‚ = ANY(ARRAY(...)).

เจŸเฉ‡เจฌเจฒ เจเจ‚เจŸเจฐเฉ€เจ†เจ‚: เจธเฉ€เจฐเฉ€เจ…เจฒเจพเจˆเจœเจผเฉ‡เจธเจผเจจ เจ…เจคเฉ‡ เจกเฉ€เจธเฉ€เจฐเฉ€เจ…เจฒเจพเจˆเจœเจผเฉ‡เจธเจผเจจ

เจชเจฐ เจ‰เจฆเฉ‹เจ‚ เจ•เฉ€ เจœเฉ‡ เจธเจพเจจเฉ‚เฉฐ เจธเจฟเจฐเจซเจผ เจ‡เฉฑเจ• เจŸเฉˆเจ•เจธเจŸ เจ–เฉ‡เจคเจฐ เจจเฉ‚เฉฐ เจนเฉ€ เจจเจนเฉ€เจ‚, เจธเจ—เฉ‹เจ‚ เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจตเจฟเฉฑเจš เจ‡เฉฑเจ• เจชเฉ‚เจฐเฉ€ เจเจ‚เจŸเจฐเฉ€ เจจเฉ‚เฉฐ เจฌเจšเจพเจ‰เจฃ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ? เจ‡เจธ เจธเจฅเจฟเจคเฉ€ เจตเจฟเฉฑเจš, PostgreSQL เจฆเฉ€ เจฏเฉ‹เจ—เจคเจพ เจธเจพเจกเฉ€ เจฎเจฆเจฆ เจ•เจฐเฉ‡เจ—เฉ€ เจ‡เฉฑเจ• เจŸเฉ‡เจฌเจฒ เจเจ‚เจŸเจฐเฉ€ เจจเฉ‚เฉฐ เจ‡เฉฑเจ• เจ‡เฉฑเจ•เจฒเฉ‡ เจฎเฉเฉฑเจฒ เจตเจœเฉ‹เจ‚ เจฎเฉฐเจจเฉ‹:

...
, dict AS (
  SELECT
    hstore(
      array_agg(id)::text[]
    , array_agg(p)::text[] -- ะผะฐะณะธั #1
    )
  FROM
    person p
  WHERE
    ...
)
SELECT
  *
, (((TABLE dict) -> author_id::text)::person).* -- ะผะฐะณะธั #2
FROM
  T;

เจ†เจ“ เจฆเฉ‡เจ–เฉ€เจ เจ•เจฟ เจ‡เฉฑเจฅเฉ‡ เจ•เฉ€ เจนเฉ‹ เจฐเจฟเจนเจพ เจธเฉ€:

  1. เจ…เจธเฉ€เจ‚ เจฒเจฟเจ† p เจชเฉ‚เจฐเฉ‡ เจตเจฟเจ…เจ•เจคเฉ€ เจŸเฉ‡เจฌเจฒ เจเจ‚เจŸเจฐเฉ€ เจฒเจˆ เจ‰เจชเจจเจพเจฎ เจตเจœเฉ‹เจ‚ เจ…เจคเฉ‡ เจ‰เจนเจจเจพเจ‚ เจฆเฉ€ เจ‡เฉฑเจ• เจฒเฉœเฉ€ เจจเฉ‚เฉฐ เจ‡เจ•เฉฑเจ เจพ เจ•เฉ€เจคเจพเฅค
  2. เจ‡เจธ เจฐเจฟเจ•เจพเจฐเจกเจฟเฉฐเจ—เจพเจ‚ เจฆเฉ€ เจฒเฉœเฉ€ เจจเฉ‚เฉฐ เจฆเฉเจฌเจพเจฐเจพ เจฌเจฃเจพเจ‡เจ† เจ—เจฟเจ† เจธเฉ€ เจ‡เจธ เจจเฉ‚เฉฐ hstore เจกเจฟเจ•เจธเจผเจจเจฐเฉ€ เจตเจฟเฉฑเจš เจฎเฉเฉฑเจฒเจพเจ‚ เจฆเฉ€ เจ‡เฉฑเจ• เจเจฐเฉ‡ เจตเจœเฉ‹เจ‚ เจฐเฉฑเจ–เจฃ เจฒเจˆ เจŸเฉˆเจ•เจธเจŸ เจธเจคเจฐเจพเจ‚ เจฆเฉ€ เจ‡เฉฑเจ• เจเจฐเฉ‡ (person[]::text[]) เจตเจฟเฉฑเจšเฅค
  3. เจœเจฆเฉ‹เจ‚ เจ…เจธเฉ€เจ‚ เจ‡เฉฑเจ• เจธเฉฐเจฌเฉฐเจงเจฟเจค เจฐเจฟเจ•เจพเจฐเจก เจชเฉเจฐเจพเจชเจค เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚, เจ…เจธเฉ€เจ‚ เจ•เฉเฉฐเจœเฉ€ เจฆเฉเจ†เจฐเจพ เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจตเจฟเฉฑเจšเฉ‹เจ‚ เจ–เจฟเฉฑเจšเจฟเจ† เจ—เจฟเจ† เจ‡เฉฑเจ• เจŸเฉˆเจ•เจธเจŸ เจธเจคเจฐ เจฆเฉ‡ เจฐเฉ‚เจช เจตเจฟเฉฑเจš.
  4. เจธเจพเจจเฉ‚เฉฐ เจŸเฉˆเจ•เจธเจŸ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ เจ‡เฉฑเจ• เจธเจพเจฐเจฃเฉ€ เจ•เจฟเจธเจฎ เจฆเฉ‡ เจฎเฉเฉฑเจฒ เจตเจฟเฉฑเจš เจฌเจฆเจฒเฉ‹ เจตเจฟเจ…เจ•เจคเฉ€ (เจนเจฐเฉ‡เจ• เจŸเฉ‡เจฌเจฒ เจฒเจˆ เจ‡เฉฑเจ•เฉ‹ เจจเจพเจฎ เจฆเฉ€ เจ‡เฉฑเจ• เจ•เจฟเจธเจฎ เจ†เจชเจฃเฉ‡ เจ†เจช เจฌเจฃ เจœเจพเจ‚เจฆเฉ€ เจนเฉˆ)เฅค
  5. เจŸเจพเจˆเจช เจ•เฉ€เจคเฉ‡ เจฐเจฟเจ•เจพเจฐเจก เจจเฉ‚เฉฐ เจ•เจพเจฒเจฎเจพเจ‚ เจตเจฟเฉฑเจš เจตเจฐเจคเจฆเฉ‡ เจนเฉ‹เจ "เจตเจฟเจธเจคเจพเจฐ เจ•เจฐเฉ‹" (...).*.

json เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ

เจชเจฐ เจ…เจœเจฟเจนเฉ€ เจšเจพเจฒ เจœเจฟเจตเฉ‡เจ‚ เจ…เจธเฉ€เจ‚ เจ‰เฉฑเจชเจฐ เจฒเจพเจ—เฉ‚ เจ•เฉ€เจคเฉ€ เจนเฉˆ เจ•เฉฐเจฎ เจจเจนเฉ€เจ‚ เจ•เจฐเฉ‡เจ—เฉ€ เจœเฉ‡เจ•เจฐ "เจ•เจพเจธเจŸเจฟเฉฐเจ—" เจ•เจฐเจจ เจฒเจˆ เจ•เฉ‹เจˆ เจ…เจจเฉเจธเจพเจฐเฉ€ เจŸเฉ‡เจฌเจฒ เจ•เจฟเจธเจฎ เจจเจนเฉ€เจ‚ เจนเฉˆเฅค เจฌเจฟเจฒเจ•เฉเจฒ เจ‰เจนเฉ€ เจธเจฅเจฟเจคเฉ€ เจชเฉˆเจฆเจพ เจนเฉ‹เจตเฉ‡เจ—เฉ€, เจ…เจคเฉ‡ เจœเฉ‡ เจ…เจธเฉ€เจ‚ เจตเจฐเจคเจฃ เจฆเฉ€ เจ•เฉ‹เจธเจผเจฟเจธเจผ เจ•เจฐเฉ€เจ เจ‡เฉฑเจ• CTE เจ•เจคเจพเจฐ, เจ‡เฉฑเจ• "เจ…เจธเจฒ" เจธเจพเจฐเจฃเฉ€ เจจเจนเฉ€เจ‚.

เจ‡เจธ เจฎเจพเจฎเจฒเฉ‡ เจตเจฟเฉฑเจš เจ‰เจน เจธเจพเจกเฉ€ เจฎเจฆเจฆ เจ•เจฐเจจเจ—เฉ‡ json เจจเจพเจฒ เจ•เฉฐเจฎ เจ•เจฐเจจ เจฒเจˆ เจซเฉฐเจ•เจธเจผเจจ:

...
, p AS ( -- ัั‚ะพ ัƒะถะต CTE
  SELECT
    *
  FROM
    person
  WHERE
    ...
)
, dict AS (
  SELECT
    json_object( -- ั‚ะตะฟะตั€ัŒ ัั‚ะพ ัƒะถะต json
      array_agg(id)::text[]
    , array_agg(row_to_json(p))::text[] -- ะธ ะฒะฝัƒั‚ั€ะธ json ะดะปั ะบะฐะถะดะพะน ัั‚ั€ะพะบะธ
    )
  FROM
    p
)
SELECT
  *
FROM
  T
, LATERAL(
    SELECT
      *
    FROM
      json_to_record(
        ((TABLE dict) ->> author_id::text)::json -- ะธะทะฒะปะตะบะปะธ ะธะท ัะปะพะฒะฐั€ั ะบะฐะบ json
      ) AS j(name text, birth_date date) -- ะทะฐะฟะพะปะฝะธะปะธ ะฝัƒะถะฝัƒัŽ ะฝะฐะผ ัั‚ั€ัƒะบั‚ัƒั€ัƒ
  ) j;

เจ‡เจน เจจเฉ‹เจŸ เจ•เฉ€เจคเจพ เจœเจพเจฃเจพ เจšเจพเจนเฉ€เจฆเจพ เจนเฉˆ เจ•เจฟ เจŸเฉ€เจšเฉ‡ เจฆเฉ€ เจฌเจฃเจคเจฐ เจฆเจพ เจตเจฐเจฃเจจ เจ•เจฐเจฆเฉ‡ เจธเจฎเฉ‡เจ‚, เจ…เจธเฉ€เจ‚ เจธเจฐเฉ‹เจค เจธเจคเจฐ เจฆเฉ‡ เจธเจพเจฐเฉ‡ เจ–เฉ‡เจคเจฐเจพเจ‚ เจจเฉ‚เฉฐ เจธเฉ‚เจšเฉ€เจฌเฉฑเจง เจจเจนเฉ€เจ‚ เจ•เจฐ เจธเจ•เจฆเฉ‡, เจชเจฐ เจธเจฟเจฐเจซ เจ‰เจนเจจเจพเจ‚ เจฆเฉ€ เจนเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ เจœเฉ‹ เจธเจพเจจเฉ‚เฉฐ เจ…เจธเจฒ เจตเจฟเฉฑเจš เจฒเฉ‹เฉœเฉ€เจ‚เจฆเฉ‡ เจนเจจเฅค เจœเฉ‡ เจธเจพเจกเฉ‡ เจ•เฉ‹เจฒ "เจฆเฉ‡เจธเฉ€" เจŸเฉ‡เจฌเจฒ เจนเฉˆ, เจคเจพเจ‚ เจซเฉฐเจ•เจธเจผเจจ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจจเจพ เจฌเจฟเจนเจคเจฐ เจนเฉˆ json_populate_record.

เจ…เจธเฉ€เจ‚ เจ…เจœเฉ‡ เจตเฉ€ เจ‡เฉฑเจ• เจตเจพเจฐ เจกเจฟเจ•เจธเจผเจจเจฐเฉ€ เจคเฉฑเจ• เจชเจนเฉเฉฐเจš เจ•เจฐเจฆเฉ‡ เจนเจพเจ‚, เจชเจฐ json-[de] เจธเฉ€เจฐเฉ€เจ…เจฒเจพเจˆเจœเจผเฉ‡เจธเจผเจจ เจฒเจพเจ—เจคเจพเจ‚ เจ•เจพเจซเจผเฉ€ เจœเจผเจฟเจ†เจฆเจพ เจนเจจ, เจ‡เจธเจฒเจˆ, เจ‡เจธ เจตเจฟเจงเฉ€ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เฉ‡เจตเจฒ เจ•เฉเจ เจฎเจพเจฎเจฒเจฟเจ†เจ‚ เจตเจฟเฉฑเจš เจนเฉ€ เจ‰เจšเจฟเจค เจนเฉˆ เจœเจฆเฉ‹เจ‚ "เจ‡เจฎเจพเจจเจฆเจพเจฐ" CTE เจธเจ•เฉˆเจจ เจ†เจชเจฃเฉ‡ เจ†เจช เจจเฉ‚เฉฐ เจนเฉ‹เจฐ เจฌเจฆเจคเจฐ เจฆเจฟเจ–เจพเจ‰เจ‚เจฆเจพ เจนเฉˆเฅค

เจŸเฉˆเจธเจŸเจฟเฉฐเจ— เจชเฉเจฐเจฆเจฐเจธเจผเจจ

เจ‡เจธ เจฒเจˆ, เจธเจพเจจเฉ‚เฉฐ เจ‡เฉฑเจ• เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจตเจฟเฉฑเจš เจกเฉ‡เจŸเจพ เจจเฉ‚เฉฐ เจฒเฉœเฉ€เจฌเฉฑเจง เจ•เจฐเจจ เจฆเฉ‡ เจฆเฉ‹ เจคเจฐเฉ€เจ•เฉ‡ เจฎเจฟเจฒเฉ‡ เจนเจจ - hstore/json_object. เจ‡เจธ เจคเฉ‹เจ‚ เจ‡เจฒเจพเจตเจพ, เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจ…เจคเฉ‡ เจฎเฉเฉฑเจฒเจพเจ‚ เจฆเฉ‡ เจเจฐเฉ‡ เจตเฉ€ เจฆเฉ‹ เจคเจฐเฉ€เจ•เจฟเจ†เจ‚ เจจเจพเจฒ เจคเจฟเจ†เจฐ เจ•เฉ€เจคเฉ‡ เจœเจพ เจธเจ•เจฆเฉ‡ เจนเจจ, เจŸเฉˆเจ•เจธเจŸ เจตเจฟเฉฑเจš เจ…เฉฐเจฆเจฐเฉ‚เจจเฉ€ เจœเจพเจ‚ เจฌเจพเจนเจฐเฉ€ เจฐเฉ‚เจชเจพเจ‚เจคเจฐเจจ เจฆเฉ‡ เจจเจพเจฒ: array_agg(i::text) / array_agg(i)::text[].

เจ†เจ‰ เจ‡เฉฑเจ• เจธเจผเฉเฉฑเจง เจธเจฟเฉฐเจฅเฉˆเจŸเจฟเจ• เจ‰เจฆเจพเจนเจฐเจจ เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจ•เฉ‡ เจตเฉฑเจ–-เจตเฉฑเจ– เจ•เจฟเจธเจฎเจพเจ‚ เจฆเฉ‡ เจธเฉ€เจฐเฉ€เจ…เจฒเจพเจˆเจœเจผเฉ‡เจธเจผเจจ เจฆเฉ€ เจชเฉเจฐเจญเจพเจตเจธเจผเฉ€เจฒเจคเจพ เจฆเฉ€ เจœเจพเจ‚เจš เจ•เจฐเฉ€เจ - เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจฆเฉ‡ เจตเฉฑเจ–-เจตเฉฑเจ– เจจเฉฐเจฌเจฐเจพเจ‚ เจจเฉ‚เฉฐ เจธเฉ€เจฐเฉ€เจ…เจฒเจพเจˆเจœเจผ เจ•เจฐเฉ‹:

WITH dict AS (
  SELECT
    hstore(
      array_agg(i::text)
    , array_agg(i::text)
    )
  FROM
    generate_series(1, ...) i
)
TABLE dict;

เจฎเฉเจฒเจพเจ‚เจ•เจฃ เจธเจ•เฉเจฐเจฟเจชเจŸ: เจธเฉ€เจฐเฉ€เจ…เจฒเจพเจˆเจœเจผเฉ‡เจธเจผเจจ

WITH T AS (
  SELECT
    *
  , (
      SELECT
        regexp_replace(ea[array_length(ea, 1)], '^Execution Time: (d+.d+) ms$', '1')::real et
      FROM
        (
          SELECT
            array_agg(el) ea
          FROM
            dblink('port= ' || current_setting('port') || ' dbname=' || current_database(), $$
              explain analyze
              WITH dict AS (
                SELECT
                  hstore(
                    array_agg(i::text)
                  , array_agg(i::text)
                  )
                FROM
                  generate_series(1, $$ || (1 << v) || $$) i
              )
              TABLE dict
            $$) T(el text)
        ) T
    ) et
  FROM
    generate_series(0, 19) v
  ,   LATERAL generate_series(1, 7) i
  ORDER BY
    1, 2
)
SELECT
  v
, avg(et)::numeric(32,3)
FROM
  T
GROUP BY
  1
ORDER BY
  1;

PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: เจ†เจ‰ เจ‡เฉฑเจ• เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจฆเฉ‡ เจจเจพเจฒ เจญเจพเจฐเฉ€ เจœเฉเจ†เจ‡เจจ เจ•เจฐเฉ€เจ

PostgreSQL 11 'เจคเฉ‡, เจฒเจ—เจญเจ— 2^12 เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจฆเฉ‡ เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจ†เจ•เจพเจฐ เจคเฉฑเจ• เจœเฉ‡เจธเจจ เจจเฉ‚เฉฐ เจธเฉ€เจฐเฉ€เจ…เจฒเจพเจˆเจœเจผ เจ•เจฐเจจ เจตเจฟเฉฑเจš เจ˜เฉฑเจŸ เจธเจฎเจพเจ‚ เจฒเฉฑเจ—เจฆเจพ เจนเฉˆ. เจ‡เจธ เจ•เฉ‡เจธ เจตเจฟเฉฑเจš, เจธเจญ เจคเฉ‹เจ‚ เจชเฉเจฐเจญเจพเจตเจธเจผเจพเจฒเฉ€ json_object เจ…เจคเฉ‡ "เจ…เฉฐเจฆเจฐเฉ‚เจจเฉ€" เจ•เจฟเจธเจฎ เจฆเฉ‡ เจฐเฉ‚เจชเจพเจ‚เจคเจฐเจฃ เจฆเจพ เจธเฉเจฎเฉ‡เจฒ เจนเฉˆเฅค array_agg(i::text).

เจนเฉเจฃ เจนเจฐ เจ•เฉเฉฐเจœเฉ€ เจฆเฉ‡ เจฎเฉเฉฑเจฒ เจจเฉ‚เฉฐ 8 เจตเจพเจฐ เจชเฉœเฉเจนเจจ เจฆเฉ€ เจ•เฉ‹เจธเจผเจฟเจธเจผ เจ•เจฐเฉ€เจ - เจ†เจ–เจฐเจ•เจพเจฐ, เจœเฉ‡เจ•เจฐ เจคเฉเจธเฉ€เจ‚ เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจคเฉฑเจ• เจจเจนเฉ€เจ‚ เจชเจนเฉเฉฐเจšเจฆเฉ‡ เจนเฉ‹, เจคเจพเจ‚ เจ‡เจธเจฆเฉ€ เจฒเฉ‹เฉœ เจ•เจฟเจ‰เจ‚ เจนเฉˆ?

เจฎเฉเจฒเจพเจ‚เจ•เจฃ เจธเจ•เฉเจฐเจฟเจชเจŸ: เจกเจฟเจ•เจธเจผเจจเจฐเฉ€ เจคเฉ‹เจ‚ เจชเฉœเฉเจนเจจเจพ

WITH T AS (
  SELECT
    *
  , (
      SELECT
        regexp_replace(ea[array_length(ea, 1)], '^Execution Time: (d+.d+) ms$', '1')::real et
      FROM
        (
          SELECT
            array_agg(el) ea
          FROM
            dblink('port= ' || current_setting('port') || ' dbname=' || current_database(), $$
              explain analyze
              WITH dict AS (
                SELECT
                  json_object(
                    array_agg(i::text)
                  , array_agg(i::text)
                  )
                FROM
                  generate_series(1, $$ || (1 << v) || $$) i
              )
              SELECT
                (TABLE dict) -> (i % ($$ || (1 << v) || $$) + 1)::text
              FROM
                generate_series(1, $$ || (1 << (v + 3)) || $$) i
            $$) T(el text)
        ) T
    ) et
  FROM
    generate_series(0, 19) v
  , LATERAL generate_series(1, 7) i
  ORDER BY
    1, 2
)
SELECT
  v
, avg(et)::numeric(32,3)
FROM
  T
GROUP BY
  1
ORDER BY
  1;

PostgreSQL เจเจ‚เจŸเฉ€เจชเฉˆเจŸเจฐเจจ: เจ†เจ‰ เจ‡เฉฑเจ• เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจฆเฉ‡ เจจเจพเจฒ เจญเจพเจฐเฉ€ เจœเฉเจ†เจ‡เจจ เจ•เจฐเฉ€เจ

เจ…เจคเฉ‡... เจชเจนเจฟเจฒเจพเจ‚ เจนเฉ€ เจฒเจ—เจญเจ— 2^6 เจ•เฉเฉฐเจœเฉ€เจ†เจ‚ เจจเจพเจฒ, เจœเฉ‡เจธเจจ เจกเจฟเจ•เจธเจผเจจเจฐเฉ€ เจคเฉ‹เจ‚ เจชเฉœเฉเจนเจจเจพ เจ•เจˆ เจตเจพเจฐ เจ—เฉเจ†เจ‰เจฃเจพ เจธเจผเฉเจฐเฉ‚ เจนเฉ‹ เจœเจพเจ‚เจฆเจพ เจนเฉˆ hstore เจคเฉ‹เจ‚ เจชเฉœเฉเจนเจจเจพ, jsonb เจฒเจˆ เจ‡เจนเฉ€ 2^9 'เจคเฉ‡ เจนเฉเฉฐเจฆเจพ เจนเฉˆเฅค

เจ…เฉฐเจคเจฎ เจธเจฟเฉฑเจŸเฉ‡:

  • เจœเฉ‡เจ•เจฐ เจคเฉเจนเจพเจจเฉ‚เฉฐ เจ‡เจน เจ•เจฐเจจ เจฆเฉ€ เจฒเฉ‹เฉœ เจนเฉˆ เจ•เจˆ เจฆเฉเจนเจฐเจพเจ‰เจฃ เจตเจพเจฒเฉ‡ เจฐเจฟเจ•เจพเจฐเจกเจพเจ‚ เจจเจพเจฒ เจœเฉเฉœเฉ‹ - เจธเจพเจฐเจฃเฉ€ เจฆเฉ€ "เจกเจ•เจธเจผเจจเจฐเฉ€" เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐเจจเจพ เจฌเจฟเจนเจคเจฐ เจนเฉˆ
  • เจœเฉ‡เจ•เจฐ เจคเฉเจนเจพเจกเฉ‡ เจธเจผเจฌเจฆเจ•เฉ‹เจธเจผ เจฆเฉ€ เจ‰เจฎเฉ€เจฆ เจ•เฉ€เจคเฉ€ เจœเจพเจ‚เจฆเฉ€ เจนเฉˆ เจ›เฉ‹เจŸเจพ เจนเฉˆ เจ…เจคเฉ‡ เจคเฉเจธเฉ€เจ‚ เจ‡เจธ เจคเฉ‹เจ‚ เจœเจผเจฟเจ†เจฆเจพ เจจเจนเฉ€เจ‚ เจชเฉœเฉเจนเฉ‹เจ—เฉ‡ - เจคเฉเจธเฉ€เจ‚ json [b] เจฆเฉ€ เจตเจฐเจคเฉ‹เจ‚ เจ•เจฐ เจธเจ•เจฆเฉ‡ เจนเฉ‹
  • เจนเฉ‹เจฐ เจธเจพเจฐเฉ‡ เจฎเจพเจฎเจฒเจฟเจ†เจ‚ เจตเจฟเฉฑเจš hstore + array_agg(i::text) เจตเจงเฉ‡เจฐเฉ‡ เจชเฉเจฐเจญเจพเจตเจธเจผเจพเจฒเฉ€ เจนเฉ‹เจตเฉ‡เจ—เจพ

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

DDoS เจธเฉเจฐเฉฑเจ–เจฟเจ†, VPS VDS เจธเจฐเจตเจฐเจพเจ‚ เจตเจพเจฒเฉ€เจ†เจ‚ เจธเจพเจˆเจŸเจพเจ‚ เจฒเจˆ เจญเจฐเฉ‹เจธเฉ‡เจฏเฉ‹เจ— เจนเฉ‹เจธเจŸเจฟเฉฐเจ— เจ–เจฐเฉ€เจฆเฉ‹ ๐Ÿ”ฅ DDoS เจธเฉเจฐเฉฑเจ–เจฟเจ†, VPS VDS เจธเจฐเจตเจฐเจพเจ‚ เจจเจพเจฒ เจญเจฐเฉ‹เจธเฉ‡เจฏเฉ‹เจ— เจตเฉˆเฉฑเจฌเจธเจพเจˆเจŸ เจนเฉ‹เจธเจŸเจฟเฉฐเจ— เจ–เจฐเฉ€เจฆเฉ‹ | ProHoster