ΠΡΠΎΠ΄ΡΠ»ΠΆΠ°Π²Π°ΠΌΠ΅ ΠΏΠΎΡΠ΅Π΄ΠΈΡΠ°ΡΠ° ΠΎΡ ΡΡΠ°ΡΠΈΠΈ, ΠΏΠΎΡΠ²Π΅ΡΠ΅Π½ΠΈ Π½Π° ΠΈΠ·ΡΡΠ°Π²Π°Π½Π΅ΡΠΎ Π½Π° ΠΌΠ°Π»ΠΊΠΎ ΠΈΠ·Π²Π΅ΡΡΠ½ΠΈ Π½Π°ΡΠΈΠ½ΠΈ Π·Π° ΠΏΠΎΠ΄ΠΎΠ±ΡΡΠ²Π°Π½Π΅ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»Π½ΠΎΡΡΡΠ° Π½Π° βΠΏΡΠΈΠ²ΠΈΠ΄Π½ΠΎ ΠΏΡΠΎΡΡΠΈβ Π·Π°ΡΠ²ΠΊΠΈ Π½Π° PostgreSQL:
ΡΡΠ΄ΡΠΊ Π·Π°ΠΏΠΈΡ ΡΠ΅ Π΄ΠΎΡΡΠΈΠ³Π½Π΅ ΡΡΠ΅Π΄Π°ΡΠ° Π½Π° JOIN Π‘ΠΈΠ·ΠΈΡΠΎΠ²ΠΈ JOIN ΠΌΠ°ΡΠΈΠ²ΠΈ Π²ΡΠ΅Π΄Π½ΠΈ JOIN ΠΈ OR CTE ΠΠ ΠΠ‘ΠͺΠΠΠΠΠΠ’Π Π‘Π Π CTE
ΠΠ΅ ΡΠΈ ΠΌΠΈΡΠ»Π΅ΡΠ΅, ΡΠ΅ Π½Π΅ Ρ Π°ΡΠ΅ΡΠ²Π°ΠΌ JOIN ΡΠΎΠ»ΠΊΠΎΠ²Π° ΠΌΠ½ΠΎΠ³ΠΎ... :)
ΠΠΎ ΡΠ΅ΡΡΠΎ Π±Π΅Π· Π½Π΅Π³ΠΎ Π·Π°ΡΠ²ΠΊΠ°ΡΠ° ΡΠ΅ ΠΎΠΊΠ°Π·Π²Π° Π·Π½Π°ΡΠΈΡΠ΅Π»Π½ΠΎ ΠΏΠΎ-ΠΏΡΠΎΠ΄ΡΠΊΡΠΈΠ²Π½Π°, ΠΎΡΠΊΠΎΠ»ΠΊΠΎΡΠΎ Ρ Π½Π΅Π³ΠΎ. Π’Π°ΠΊΠ° ΡΠ΅ Π΄Π½Π΅Ρ ΡΠ΅ ΠΎΠΏΠΈΡΠ°ΠΌΠ΅ ΠΎΡΡΡΠ²Π΅ΡΠ΅ ΡΠ΅ ΠΎΡ ΡΠ΅ΡΡΡΡΠΎΠ΅ΠΌΠΊΠΈΡ JOIN - ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° ΡΠ΅ΡΠ½ΠΈΠΊ.
ΠΠ°ΠΏΠΎΡΠ²Π°ΠΉΠΊΠΈ Ρ 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;
ΠΠΊΠ°Π·Π²Π° ΡΠ΅, ΡΠ΅ 1/3 ΠΎΠ±ΡΠΎ Π²ΡΠ΅ΠΌΠ΅ ΠΈ 3/4 ΡΠ΅ΡΠ΅Π½ΠΈΡ ΡΡΡΠ°Π½ΠΈΡΠΈ Ρ Π΄Π°Π½Π½ΠΈ Π±ΡΡ Π° Π½Π°ΠΏΡΠ°Π²Π΅Π½ΠΈ ΡΠ°ΠΌΠΎ Π·Π° ΡΡΡΡΠ΅Π½Π΅ Π½Π° Π°Π²ΡΠΎΡΠ° 100 ΠΏΡΡΠΈ - Π·Π° Π²ΡΡΠΊΠ° ΠΈΠ·Ρ ΠΎΠ΄Π½Π° Π·Π°Π΄Π°ΡΠ°. ΠΠΎ Π·Π½Π°Π΅ΠΌ, ΡΠ΅ ΡΡΠ΅Π΄ ΡΠ΅Π·ΠΈ ΡΡΠΎΡ ΡΠ°ΠΌΠΎ 20 ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ - ΠΡΠ·ΠΌΠΎΠΆΠ½ΠΎ Π»ΠΈ Π΅ Π΄Π° ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ ΡΠ΅Π·ΠΈ Π·Π½Π°Π½ΠΈΡ?
hstore-ΡΠ΅ΡΠ½ΠΈΠΊ
ΠΠ° ΡΠ΅ ββΠ²ΡΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅
CREATE EXTENSION hstore
ΠΡΠΎΡΡΠΎ ΡΡΡΠ±Π²Π° Π΄Π° ΠΏΠΎΡΡΠ°Π²ΠΈΠΌ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΎΠ½Π½ΠΈΡ Π½ΠΎΠΌΠ΅Ρ Π½Π° Π°Π²ΡΠΎΡΠ° ΠΈ ΠΈΠΌΠ΅ΡΠΎ ΠΌΡ Π² ΡΠ΅ΡΠ½ΠΈΠΊΠ°, Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ΠΌ ΡΠ»Π΅Π΄ ΡΠΎΠ²Π° Π΄Π° ΠΈΠ·Π²Π»Π΅ΡΠ΅ΠΌ Ρ ΡΠΎΠ·ΠΈ ΠΊΠ»ΡΡ:
-- ΡΠΎΡΠΌΠΈΡΡΠ΅ΠΌ ΡΠ΅Π»Π΅Π²ΡΡ Π²ΡΠ±ΠΎΡΠΊΡ
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;
Π Π°Π·Ρ
ΠΎΠ΄Π²Π°Π½ΠΈ Π·Π° ΠΏΠΎΠ»ΡΡΠ°Π²Π°Π½Π΅ Π½Π° ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ Π·Π° Π»ΠΈΡΠ° 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;
ΠΠ΅ΠΊΠ° Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊΠ²ΠΎ ΡΠ΅ ΡΠ»ΡΡΠ²Π° ΡΡΠΊ:
- ΠΠ·Π΅Ρ ΠΌΠ΅ p ΠΊΠ°ΡΠΎ ΠΏΡΠ΅Π²Π΄ΠΎΠ½ΠΈΠΌ Π½Π° Π·Π°ΠΏΠΈΡΠ° Π² ΠΏΡΠ»Π½Π°ΡΠ° ΡΠ°Π±Π»ΠΈΡΠ° Ρ Π»ΠΈΡΠ° ΠΈ ΡΡΠ±ΡΠ° ΠΌΠ°ΡΠΈΠ² ΠΎΡ ΡΡΡ .
- ΡΠΎΠ²Π° ΠΌΠ°ΡΠΈΠ²ΡΡ ΠΎΡ Π·Π°ΠΏΠΈΡΠΈ Π±Π΅ΡΠ΅ ΠΏΡΠ΅ΡΠ°Π±ΠΎΡΠ΅Π½ ΠΊΡΠΌ ΠΌΠ°ΡΠΈΠ² ΠΎΡ ΡΠ΅ΠΊΡΡΠΎΠ²ΠΈ Π½ΠΈΠ·ΠΎΠ²Π΅ (person[]::text[]), Π·Π° Π΄Π° Π³ΠΎ ΠΏΠΎΡΡΠ°Π²ΠΈΡΠ΅ Π² ΡΠ΅ΡΠ½ΠΈΠΊΠ° Π½Π° hstore ΠΊΠ°ΡΠΎ ΠΌΠ°ΡΠΈΠ² ΠΎΡ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ.
- ΠΠΎΠ³Π°ΡΠΎ ΠΏΠΎΠ»ΡΡΠΈΠΌ ΡΠ²ΡΡΠ·Π°Π½ Π·Π°ΠΏΠΈΡ, Π½ΠΈΠ΅ ΠΈΠ·ΡΠ΅Π³Π»Π΅Π½ ΠΎΡ ΡΠ΅ΡΠ½ΠΈΠΊΠ° ΠΏΠΎ ΠΊΠ»ΡΡ ΠΊΠ°ΡΠΎ ΡΠ΅ΠΊΡΡΠΎΠ² Π½ΠΈΠ·.
- ΠΠΌΠ°ΠΌΠ΅ Π½ΡΠΆΠ΄Π° ΠΎΡ ΡΠ΅ΠΊΡΡ ΠΏΡΠ΅Π²ΡΡΠ½Π΅ Π² ΡΡΠΎΠΉΠ½ΠΎΡΡ ΠΎΡ ΡΠΈΠΏ ΡΠ°Π±Π»ΠΈΡΠ° ΡΠΎΠ²Π΅ΠΊ (Π·Π° Π²ΡΡΠΊΠ° ΡΠ°Π±Π»ΠΈΡΠ° Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ½ΠΎ ΡΠ΅ ΡΡΠ·Π΄Π°Π²Π° ΡΠΈΠΏ ΡΡΡ ΡΡΡΠΎΡΠΎ ΠΈΠΌΠ΅).
- βΠ Π°Π·ΡΠΈΡΠ΅ΡΠ΅β Π²ΡΠ²Π΅Π΄Π΅Π½ΠΈΡ Π·Π°ΠΏΠΈΡ Π² ΠΊΠΎΠ»ΠΎΠ½ΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΠ° Π½Π°
(...).*
.
json ΡΠ΅ΡΠ½ΠΈΠΊ
ΠΠΎ ΡΠ°ΠΊΡΠ² ΡΡΠΈΠΊ, ΠΊΠΎΠΉΡΠΎ ΠΏΡΠΈΠ»ΠΎΠΆΠΈΡ ΠΌΠ΅ ΠΏΠΎ-Π³ΠΎΡΠ΅, Π½ΡΠΌΠ° Π΄Π° ΡΠ°Π±ΠΎΡΠΈ, Π°ΠΊΠΎ Π½ΡΠΌΠ° ΡΡΠΎΡΠ²Π΅ΡΠ΅Π½ ΡΠΈΠΏ ΡΠ°Π±Π»ΠΈΡΠ°, Π·Π° Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈ βΠΊΠ°ΡΡΠΈΠ½Π³ΡΡβ. Π’ΠΎΡΠ½ΠΎ ΡΡΡΠ°ΡΠ° ΡΠΈΡΡΠ°ΡΠΈΡ ΡΠ΅ Π²ΡΠ·Π½ΠΈΠΊΠ½Π΅ ΠΈ Π°ΠΊΠΎ ΡΠ΅ ΠΎΠΏΠΈΡΠ°ΠΌΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ CTE ΡΠ΅Π΄, Π° Π½Π΅ "ΠΈΡΡΠΈΠ½ΡΠΊΠ°" ΡΠ°Π±Π»ΠΈΡΠ°.
Π ΡΠΎΠ·ΠΈ ΡΠ»ΡΡΠ°ΠΉ ΡΠ΅ ΡΠ΅ Π½ΠΈ ΠΏΠΎΠΌΠΎΠ³Π½Π°Ρ
...
, 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 11, ΠΏΡΠΈΠ±Π»ΠΈΠ·ΠΈΡΠ΅Π»Π½ΠΎ Π΄ΠΎ ΡΠ°Π·ΠΌΠ΅Ρ Π½Π° ΡΠ΅ΡΠ½ΠΈΠΊΠ° ΠΎΡ 2^12 ΠΊΠ»ΡΡΠ° ΡΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠ°Π½Π΅ΡΠΎ Π² json ΠΎΡΠ½Π΅ΠΌΠ° ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ Π²ΡΠ΅ΠΌΠ΅. Π ΡΠΎΠ·ΠΈ ΡΠ»ΡΡΠ°ΠΉ Π½Π°ΠΉ-Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½Π° Π΅ ΠΊΠΎΠΌΠ±ΠΈΠ½Π°ΡΠΈΡΡΠ° ΠΎΡ 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;
Π... Π²Π΅ΡΠ΅ ΠΏΡΠΈΠ±Π»ΠΈΠ·ΠΈΡΠ΅Π»Π½ΠΎ Ρ 2^6 ΠΊΠ»ΡΡΠ° ΡΠ΅ΡΠ΅Π½Π΅ΡΠΎ ΠΎΡ json ΡΠ΅ΡΠ½ΠΈΠΊ Π·Π°ΠΏΠΎΡΠ²Π° Π΄Π° ΡΠ΅ Π³ΡΠ±ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡΠ°ΡΠ½ΠΎ ΡΠ΅ΡΠ΅Π½Π΅ ΠΎΡ hstore, Π·Π° jsonb ΡΡΡΠΎΡΠΎ ΡΠ΅ ΡΠ»ΡΡΠ²Π° ΠΏΡΠΈ 2^9.
ΠΠΊΠΎΠ½ΡΠ°ΡΠ΅Π»Π½ΠΈ Π·Π°ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ:
- Π°ΠΊΠΎ ΡΡΡΠ±Π²Π° Π΄Π° Π³ΠΎ Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ΅ ΠΠ ΠΠ‘ΠͺΠΠΠΠΠΠ’Π ΡΠ΅ Ρ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ ΠΏΠΎΠ²ΡΠ°ΡΡΡΠΈ ΡΠ΅ Π·Π°ΠΏΠΈΡΠΈ β ΠΏΠΎ-Π΄ΠΎΠ±ΡΠ΅ Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ βΡΠ΅ΡΠ½ΠΈΠΊβ Π½Π° ΡΠ°Π±Π»ΠΈΡΠ°ΡΠ°
- Π°ΠΊΠΎ ΡΠ΅ ΠΎΡΠ°ΠΊΠ²Π° Π²Π°ΡΠΈΡΡ ΡΠ΅ΡΠ½ΠΈΠΊ ΠΌΠ°Π»ΡΠΊ ΠΈ Π½ΡΠΌΠ° Π΄Π° ΠΏΡΠΎΡΠ΅ΡΠ΅ΡΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΡ Π½Π΅Π³ΠΎ - ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅ json[b]
- Π²ΡΠ² Π²ΡΠΈΡΠΊΠΈ ΠΎΡΡΠ°Π½Π°Π»ΠΈ ΡΠ»ΡΡΠ°ΠΈ hstore + array_agg(i::ΡΠ΅ΠΊΡΡ) ΡΠ΅ Π±ΡΠ΄Π΅ ΠΏΠΎ-Π΅ΡΠ΅ΠΊΡΠΈΠ²Π΅Π½
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: www.habr.com