์ ๋ฌด์ ๊ฐ๋ฐ์๊ฐ ์์ฒญ์ ์์ฑํ๊ณ ''๋ผ๊ณ ์๊ฐํ๋ ์ํฉ์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.๋ฒ ์ด์ค๋ ์ค๋งํธํด์ ๋ชจ๋ ๊ฒ์ ์์ฒด์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค!ยซ
์ด๋ค ๊ฒฝ์ฐ์๋(๋ถ๋ถ์ ์ผ๋ก๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ธฐ๋ฅ์ ๋ํ ๋ฌด์ง, ๋ถ๋ถ์ ์ผ๋ก๋ ์กฐ๊ธฐ ์ต์ ํ๋ก ์ธํด) ์ด๋ฌํ ์ ๊ทผ ๋ฐฉ์์ผ๋ก ์ธํด "ํ๋์ผ์ํ์ธ"์ด ๋ํ๋ฉ๋๋ค.
๋จผ์ ๊ทธ๋ฌํ ์์ฒญ์ ์๋ฅผ ๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
-- ะดะปั ะบะฐะถะดะพะน ะบะปััะตะฒะพะน ะฟะฐัั ะฝะฐั
ะพะดะธะผ ะฐััะพัะธะธัะพะฒะฐะฝะฝัะต ะทะฝะฐัะตะฝะธั ะฟะพะปะตะน
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);
๊ทธ๊ฒ์ ๋ฐํ์ก๋ค ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๋ฐ XNUMX/XNUMX๋ ์ฑ ๊ฑธ๋ฆฌ์ง ์์์ต๋๋ค. ์ฟผ๋ฆฌ ์คํ:
ํ์กฐ๊ฐ์ฉ ๋ถํดํด์
์์ฒญ์ ์์ธํ ์ดํด๋ณด๊ณ ๋นํฉํด ๋ด ์๋ค.
- ์ฌ๊ท์ CTE๊ฐ ์๋๋ฐ ์ ์ฌ๊ธฐ์ WITH RECURSIVE๊ฐ ์๋์?
- ์ด์จ๋ ์๋ณธ ์ํ์ ์ฐ๊ฒฐ๋์ด ์๋ ๊ฒฝ์ฐ ์ต์/์ต๋ ๊ฐ์ ๋ณ๋์ CTE๋ก ๊ทธ๋ฃนํํ๋ ์ด์ ๋ ๋ฌด์์
๋๊น?
+25% ์๊ฐ - ์ด์ CTE๋ฅผ ๋ฐ๋ณตํ๊ธฐ ์ํด ๋์ ๋ฌด์กฐ๊ฑด 'SELECT * FROM'์ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ฌด์์
๋๊น?
+14% ์๊ฐ
์ด ๊ฒฝ์ฐ ์ฐ๊ฒฐ์ Nested Loop๊ฐ ์๋ Hash Join์ด ์ ํ๋์๋ค๋ ์ ์ ๋งค์ฐ ์ด์ด ์ข์์ต๋๋ค. ์๋ํ๋ฉด CTE ์ค์บ ํจ์ค ํ๋๋ง์ด ์๋๋ผ 10K๋ฅผ ๋ฐ์๊ธฐ ๋๋ฌธ์ ๋๋ค!
CTE ์ค์บ์ ๋ํด ์กฐ๊ธ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ๊ธฐ์ตํด์ผ ํฉ๋๋ค. CTE ์ค์บ์ Seq ์ค์บ๊ณผ ์ ์ฌํฉ๋๋ค. - ์ฆ, ์์ธ์ ์์ฑํ์ง ์๊ณ ์ ์ฒด ๊ฒ์๋ง ์ํํฉ๋๋ค. 10K x 0.3ms = 3000ms cte_max์ ์ฌ์ดํด์ฉ ๋๋ 1K x 1.5ms = 1500ms cte_bind๋ก ๋ฐ๋ณตํ ๋!
์ฌ์ค, ๊ทธ ๊ฒฐ๊ณผ ๋ฌด์์ ์ป๊ณ ์ถ์๋์? ๋ค, ๋ณดํต "5์ธต" ์ฟผ๋ฆฌ๋ฅผ ๋ถ์ํ๋ XNUMX๋ถ ์ ๋์ ์ด๋ฐ ์ง๋ฌธ์ด ๋์ต๋๋ค.
์ฐ๋ฆฌ๋ ๊ฐ๊ฐ์ ๊ณ ์ ํ ํค ์์ ๋ํด ์ถ๋ ฅ์ ์ํ์ต๋๋ค. 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);
๋ ์ต์ ๋ชจ๋์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๋ ๋ฐ ์ฝ 4-5ms๊ฐ ๊ฑธ๋ฆฌ๋ฏ๋ก ๋ชจ๋ ์๊ฐ์ด ๋์ด๋ฉ๋๋ค. -32 % - ์ด๊ฒ์ ๊ฐ์ฅ ์์ํ ํํ์ด๋ค. ๊ธฐ๋ณธ CPU์์ ๋ถํ๊ฐ ์ ๊ฑฐ๋จ, ๊ทธ๋ฌํ ์์ฒญ์ด ์ถฉ๋ถํ ์์ฃผ ์คํ๋๋ ๊ฒฝ์ฐ.
์ผ๋ฐ์ ์ผ๋ก ๋ฒ ์ด์ค์ "๋ฅ๊ทผ ๊ฒ์ ๋ค๊ณ ๋ค๋ชจ๋ ๊ตด๋ฆฐ๋ค"๊ณ ๊ฐ์ํด์๋ ์ ๋ฉ๋๋ค.
์ถ์ฒ : habr.com