๋ฒํผ๋ฅผ ๊ฐ์ ธ์ค๋ ์์
์ ์ฃผ์ํ์ธ์...
์๋ฅผ ๋ค์ด ์์ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ PostgreSQL์์ ์ฟผ๋ฆฌ๋ฅผ ์ต์ ํํ๊ธฐ์ํ ๋ช ๊ฐ์ง ๋ณดํธ์ ์ธ ์ ๊ทผ ๋ฐฉ์์ ์ดํด ๋ณด๊ฒ ์ต๋๋ค. ๋น์ ์ด ๊ทธ๊ฒ๋ค์ ์ฌ์ฉํ๋ ์๋๋ ๋น์ ์๊ฒ ๋ฌ๋ ค ์์ง๋ง, ๊ทธ๋ค์ ๋ํด ์๋ ๊ฒ์ด ์ข์ต๋๋ค.
์ผ๋ถ ํ์ ๋ฒ์ ์ PG์์๋ ์ค์ผ์ค๋ฌ๊ฐ ๋ ๋๋ํด์ง๋ฉด ์ํฉ์ด ๋ณ๊ฒฝ ๋ ์ ์์ง๋ง 9.4/9.6์ ๊ฒฝ์ฐ ์ฌ๊ธฐ์ ์์์์ ๊ฑฐ์ ๋์ผํ๊ฒ ๋ณด์
๋๋ค.
๋งค์ฐ ์ค์ ์ ์ธ ์์ฒญ์ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
SELECT
TRUE
FROM
"ะะพะบัะผะตะฝั" d
INNER JOIN
"ะะพะบัะผะตะฝัะ ะฐััะธัะตะฝะธะต" doc_ex
USING("@ะะพะบัะผะตะฝั")
INNER JOIN
"ะขะธะฟะะพะบัะผะตะฝัะฐ" t_doc ON
t_doc."@ะขะธะฟะะพะบัะผะตะฝัะฐ" = d."ะขะธะฟะะพะบัะผะตะฝัะฐ"
WHERE
(d."ะะธัะพ3" = 19091 or d."ะกะพัััะดะฝะธะบ" = 19091) AND
d."$ะงะตัะฝะพะฒะธะบ" IS NULL AND
d."ะฃะดะฐะปะตะฝ" IS NOT TRUE AND
doc_ex."ะกะพััะพัะฝะธะต"[1] IS TRUE AND
t_doc."ะขะธะฟะะพะบัะผะตะฝัะฐ" = 'ะะปะฐะฝะ ะฐะฑะพั'
LIMIT 1;
ํ
์ด๋ธ ๋ฐ ํ๋ ์ด๋ฆ์ ๋ํดํ๋์ ํ
์ด๋ธ์ "๋ฌ์์์ด" ์ด๋ฆ์ ๋ค๋ฅด๊ฒ ์ทจ๊ธ๋ ์ ์์ง๋ง ์ด๋ ์ทจํฅ์ ๋ฌธ์ ์
๋๋ค. ์๋ํ๋ฉด
๊ฒฐ๊ณผ ๊ณํ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
144ms ๋ฐ ๊ฑฐ์ 53K ๋ฒํผ - ์ฆ, 400MB ์ด์์ ๋ฐ์ดํฐ์ ๋๋ค! ๊ทธ๋ฆฌ๊ณ ์์ฒญ ์์ ์ ๋ชจ๋ ํญ๋ชฉ์ด ์บ์์ ์์ผ๋ฉด ์ด์ด ์ข์ ๊ฒ์ ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ๋์คํฌ์์ ์ฝ์ ๋ ์๊ฐ์ด ๋ช ๋ฐฐ ๋ ์ค๋ ๊ฑธ๋ฆด ๊ฒ์ ๋๋ค.
์๊ณ ๋ฆฌ์ฆ์ด ๊ฐ์ฅ ์ค์ํฉ๋๋ค!
์์ฒญ์ ์ด๋ป๊ฒ๋ ์ต์ ํํ๋ ค๋ฉด ๋จผ์ ์์ฒญ์ด ์ํํด์ผ ํ๋ ์์
์ ์ดํดํด์ผ ํฉ๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ตฌ์กฐ ์์ฒด์ ๊ฐ๋ฐ์ ๋ํด์๋ ์ง๊ธ์ ์ด ๊ธฐ์ฌ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋์ ์๋์ ์ผ๋ก "์ ๋ ดํ๊ฒ" ํ ์ ์๋ค๋ ์ ์ ๋์ํ๊ฒ ์ต๋๋ค. ์์ฒญ์ ๋ค์ ์์ฑ ๊ทธ๋ฆฌ๊ณ /๋๋ ์ฐ๋ฆฌ์๊ฒ ํ์ํ ๊ฒ๋ค์ ๋ฐ๋ฅ์ ๊ตด๋ ค ๋์ ์๋ ์์ต๋๋ค ์์ธ.
๋ฐ๋ผ์ ์์ฒญ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
โ ์ ์ด๋ ์ผ๋ถ ๋ฌธ์์ ์กด์ฌ ์ฌ๋ถ๋ฅผ ํ์ธํฉ๋๋ค.
- ์ฐ๋ฆฌ๊ฐ ํ์๋ก ํ๋ ํน์ ์ ํ์ ์กฐ๊ฑด์์
- ์ ์๋ ์ํ์๊ฐ ์ฐ๋ฆฌ์๊ฒ ํ์ํ ์ง์์ธ ๊ฒฝ์ฐ
๊ฐ์ + ์ ํ 1
๋ง์ ์์ ํ
์ด๋ธ์ด ์ฒ์ ์กฐ์ธ๋ ๋ค์ ์ ์ฒด ์ธํธ์์ ํ๋์ ๋ ์ฝ๋๋ง ๋จ๊ฒ ๋๋ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ๋ฐ์๊ฐ ์์ฑํ๋ ๊ฒ์ด ๋ ์ฌ์ด ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ๋ฐ์์๊ฒ ๋ ์ฝ๋ค๊ณ ํด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ ํจ์จ์ ์ด๋ผ๋ ์๋ฏธ๋ ์๋๋๋ค.
์ฐ๋ฆฌ์ ๊ฒฝ์ฐ์๋ ํ
์ด๋ธ์ด 3๊ฐ๋ฟ์ด์์ต๋๋ค. ๊ทธ ํจ๊ณผ๋ ๋ฌด์์
๋๊น?
๋จผ์ "Document Type" ํ ์ด๋ธ๊ณผ์ ์ฐ๊ฒฐ์ ์ ๊ฑฐํ๊ณ ๋์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ค์์ ์๋ ค์ค๋๋ค. ์ฐ๋ฆฌ์ ์ ํ ๋ ์ฝ๋๋ ๋ ํนํฉ๋๋ค (์ฐ๋ฆฌ๋ ์ด๊ฒ์ ์๊ณ ์์ง๋ง ์ค์ผ์ค๋ฌ๋ ์์ง ๋ชจ๋ฆ ๋๋ค):
WITH T AS (
SELECT
"@ะขะธะฟะะพะบัะผะตะฝัะฐ"
FROM
"ะขะธะฟะะพะบัะผะตะฝัะฐ"
WHERE
"ะขะธะฟะะพะบัะผะตะฝัะฐ" = 'ะะปะฐะฝะ ะฐะฑะพั'
LIMIT 1
)
...
WHERE
d."ะขะธะฟะะพะบัะผะตะฝัะฐ" = (TABLE T)
...
์, ํ ์ด๋ธ/CTE๊ฐ ๋จ์ผ ๋ ์ฝ๋์ ๋จ์ผ ํ๋๋ก ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ PG์์๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์๋ ์์ต๋๋ค.
d."ะขะธะฟะะพะบัะผะตะฝัะฐ" = (SELECT "@ะขะธะฟะะพะบัะผะตะฝัะฐ" FROM T LIMIT 1)
PostgreSQL ์ฟผ๋ฆฌ์ ์ง์ฐ ํ๊ฐ
๋นํธ๋งต๋๋ UNION
์ด๋ค ๊ฒฝ์ฐ์๋ ๋นํธ๋งต ํ ์ค์บ์ ๋ง์ ๋น์ฉ์ด ๋ค ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๊ฝค ๋ง์ ๋ ์ฝ๋๊ฐ ํ์ ์กฐ๊ฑด์ ์ถฉ์กฑํ๋ ์ํฉ์์๋ ๊ทธ๋ ์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ์ป์์ต๋๋ค ์๋ํ๋ฉด OR ์กฐ๊ฑด์ด BitmapOr๋ก ๋ฐ๋์์ต๋๋ค.- ๊ณํ๋๋ก ์ด์ ์ค.
์๋ ๋ฌธ์ ๋ก ๋์๊ฐ ๋ณด๊ฒ ์ต๋๋ค. ์ด์ ํด๋นํ๋ ๋ ์ฝ๋๋ฅผ ์ฐพ์์ผ ํฉ๋๋ค. ์ด๋ ๋๊ตฌ์๊ฒ ์ฆ, ๋ ์กฐ๊ฑด ๋ชจ๋์์ 59K ๋ ์ฝ๋๋ฅผ ๋ชจ๋ ๊ฒ์ํ ํ์๊ฐ ์์ต๋๋ค. ํ ๊ฐ์ง ์กฐ๊ฑด์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ด ์์ผ๋ฉฐ, ์ฒซ ๋ฒ์งธ์์ ์๋ฌด๊ฒ๋ ๋ฐ๊ฒฌ๋์ง ์์์ ๋๋ง ๋ ๋ฒ์งธ๋ก ์ด๋. ๋ค์ ๋์์ธ์ด ๋์์ด ๋ ๊ฒ์
๋๋ค.
(
SELECT
...
LIMIT 1
)
UNION ALL
(
SELECT
...
LIMIT 1
)
LIMIT 1
"์ธ๋ถ" LIMIT 1์ ์ฒซ ๋ฒ์งธ ๋ ์ฝ๋๊ฐ ๋ฐ๊ฒฌ๋๋ฉด ๊ฒ์์ด ์ข ๋ฃ๋๋๋ก ๋ณด์ฅํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฒซ ๋ฒ์งธ ๋ธ๋ก์์ ์ด๋ฏธ ๋ฐ๊ฒฌ๋ ๊ฒฝ์ฐ ๋ ๋ฒ์งธ ๋ธ๋ก์ ์คํ๋์ง ์์ต๋๋ค(ํ๋ฒ๋ ์ฒํ๋ ์ ์ด ์๋ค ์ ๊ดํ์ฌ).
"์ฌ๊ฑด์์ ์ด๋ ค์ด ์กฐ๊ฑด์ ์จ๊ธฐ๊ธฐ"
์๋ ์ฟผ๋ฆฌ์๋ ๊ด๋ จ ํ
์ด๋ธ "DocumentExtension"์ ๋ํด ์ํ๋ฅผ ํ์ธํ๋ ๋งค์ฐ ๋ถํธํ ์๊ฐ์ด ์์ต๋๋ค. ํํ์ ๋ค๋ฅธ ์กฐ๊ฑด์ด ์ฐธ์ธ์ง ์ฌ๋ถ์ ๊ด๊ณ์์ด(์: d.โ์ญ์ โ๋ ์ฌ์ค์ด ์๋๋๋ค.), ์ด ์ฐ๊ฒฐ์ ํญ์ ์คํ๋๋ฉฐ "๋ฆฌ์์ค ๋น์ฉ์ด ๋ฐ์"ํฉ๋๋ค. ๊ทธ ์ค ์ด๋ ์ ๋๋ ์๋น๋ฉ๋๋ค. ์ด ํ
์ด๋ธ์ ํฌ๊ธฐ์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค.
๊ทธ๋ฌ๋ ๊ด๋ จ ๋ ์ฝ๋ ๊ฒ์์ด ์ค์ ๋ก ํ์ํ ๊ฒฝ์ฐ์๋ง ๋ฐ์ํ๋๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ ํ ์ ์์ต๋๋ค.
SELECT
...
FROM
"ะะพะบัะผะตะฝั" d
WHERE
... /*index cond*/ AND
CASE
WHEN "$ะงะตัะฝะพะฒะธะบ" IS NULL AND "ะฃะดะฐะปะตะฝ" IS NOT TRUE THEN (
SELECT
"ะกะพััะพัะฝะธะต"[1] IS TRUE
FROM
"ะะพะบัะผะตะฝัะ ะฐััะธัะตะฝะธะต"
WHERE
"@ะะพะบัะผะตะฝั" = d."@ะะพะบัะผะตะฝั"
)
END
๋งํฌ ๋ ํ
์ด๋ธ์์ ์ฐ๋ฆฌ์๊ฒ ํ ๋ฒ ๊ฒฐ๊ณผ์๋ ํ๋๊ฐ ํ์ํ์ง ์์ต๋๋ค., ๊ทธ๋ฐ ๋ค์ JOIN์ ํ์ ์ฟผ๋ฆฌ์ ์กฐ๊ฑด์ผ๋ก ๋ฐ๊ฟ ์ ์๋ ๊ธฐํ๊ฐ ์์ต๋๋ค.
์ธ๋ฑ์ค ๋ ํ๋๋ฅผ "์ผ์ด์ค ๋ธ๋ํท ์ธ๋ถ"๋ก๋๊ณ ๋ ์ฝ๋์์ when ๋ธ๋ก์ผ๋ก ๊ฐ๋จํ ์กฐ๊ฑด์ ์ถ๊ฐํ๊ฒ ์ต๋๋ค. ์ด์ "๋ฌด๊ฑฐ์ด"์ฟผ๋ฆฌ๋ ํต๊ณผ ํ ๋๋ง ์คํ๋ฉ๋๋ค.
๋ด ์ฑ์ "ํ ํ"์ด์์
๊ฒฐ๊ณผ ์ฟผ๋ฆฌ๋ฅผ ์์์ ์ค๋ช ํ ๋ชจ๋ ๋ฉ์ปค๋์ฆ์ผ๋ก ์์งํฉ๋๋ค.
WITH T AS (
SELECT
"@ะขะธะฟะะพะบัะผะตะฝัะฐ"
FROM
"ะขะธะฟะะพะบัะผะตะฝัะฐ"
WHERE
"ะขะธะฟะะพะบัะผะตะฝัะฐ" = 'ะะปะฐะฝะ ะฐะฑะพั'
)
(
SELECT
TRUE
FROM
"ะะพะบัะผะตะฝั" d
WHERE
("ะะธัะพ3", "ะขะธะฟะะพะบัะผะตะฝัะฐ") = (19091, (TABLE T)) AND
CASE
WHEN "$ะงะตัะฝะพะฒะธะบ" IS NULL AND "ะฃะดะฐะปะตะฝ" IS NOT TRUE THEN (
SELECT
"ะกะพััะพัะฝะธะต"[1] IS TRUE
FROM
"ะะพะบัะผะตะฝัะ ะฐััะธัะตะฝะธะต"
WHERE
"@ะะพะบัะผะตะฝั" = d."@ะะพะบัะผะตะฝั"
)
END
LIMIT 1
)
UNION ALL
(
SELECT
TRUE
FROM
"ะะพะบัะผะตะฝั" d
WHERE
("ะขะธะฟะะพะบัะผะตะฝัะฐ", "ะกะพัััะดะฝะธะบ") = ((TABLE T), 19091) AND
CASE
WHEN "$ะงะตัะฝะพะฒะธะบ" IS NULL AND "ะฃะดะฐะปะตะฝ" IS NOT TRUE THEN (
SELECT
"ะกะพััะพัะฝะธะต"[1] IS TRUE
FROM
"ะะพะบัะผะตะฝัะ ะฐััะธัะตะฝะธะต"
WHERE
"@ะะพะบัะผะตะฝั" = d."@ะะพะบัะผะตะฝั"
)
END
LIMIT 1
)
LIMIT 1;
[to] ์ธ๋ฑ์ค ์กฐ์
ํ๋ จ๋ ๋์ UNION ํ์ ๋ธ๋ก์ ์ธ๋ฑ์ค ์กฐ๊ฑด์ด ์ฝ๊ฐ ๋ค๋ฅด๋ค๋ ๊ฒ์ ์์์ฐจ๋ ธ์ต๋๋ค. ์ด๋ ์ด๋ฏธ ํ
์ด๋ธ์ ์ ํฉํ ์ธ๋ฑ์ค๊ฐ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ์กด์ฌํ์ง ์๋๋ค๋ฉด, ๋ง๋ค์ด ๋ณผ ๊ฐ์น๊ฐ ์์ ๊ฒ์
๋๋ค: ๋ฌธ์(Person3, ๋ฌธ์ ์ ํ) ะธ ๋ฌธ์(๋ฌธ์ ์ ํ, ์ง์).
ํ ์กฐ๊ฑด์์ ํ๋์ ์์์ ๋ํด๊ธฐํ์ ์
์ฅ์์๋ ๋ฌผ๋ก ์ธ ์๋ ์๊ฒ ์ง๋ง (A, B) = (constA, constB)๊ณผ (B, A) = (constB, constA). ํ์ง๋ง ๋
น์ํ ๋ ์ธ๋ฑ์ค์ ํ๋ ์์๋๋ก, ์ด๋ฌํ ์์ฒญ์ ๋์ค์ ๋๋ฒ๊น
ํ๋ ๊ฒ์ด ๋ ํธ๋ฆฌํฉ๋๋ค.
๊ณํ์๋ ๋ฌด์์ด ์๋์?
๋ถํํ๊ฒ๋ ์ฐ๋ฆฌ๋ ์ด์ด ์ข์ง ์์๊ณ ์ฒซ ๋ฒ์งธ UNION ๋ธ๋ก์์๋ ์๋ฌด ๊ฒ๋ ๋ฐ๊ฒฌ๋์ง ์์๊ธฐ ๋๋ฌธ์ ๋ ๋ฒ์งธ UNION ๋ธ๋ก์ด ์ฌ์ ํ ์คํ๋์์ต๋๋ค. ํ์ง๋ง ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ - ๋จ์ง 0.037ms ๋ฐ 11๊ฐ ๋ฒํผ!
์์ฒญ ์๋๋ฅผ ๋์ด๊ณ ๋ฉ๋ชจ๋ฆฌ์ ๋ฐ์ดํฐ ํํ์ ์ค์์ต๋๋ค. ์์ฒ ๋ฒ, ๋งค์ฐ ๊ฐ๋จํ ๊ธฐ์ ์ ์ฌ์ฉํ์ฌ ์ฝ๊ฐ์ ๋ณต์ฌ-๋ถ์ฌ๋ฃ๊ธฐ๋ก ์ข์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค. ๐
์ถ์ฒ : habr.com