2024. 1. 21. 22:18ใDatabase/DB ์คํฐ๋
๊ฐ์ธ์ ์ธ ๊ฒฝํ ์, ์ทจ์ ์ ์ค๋นํ๋ ๊ฐ๋ฐ์ ์ง๋ง์ ๋ถ๋ค์ด๋ ํน์ ์ ์ ๋ด์ง ์ฃผ๋์ด ๊ฐ๋ฐ์ ๋ถ๋ค ์ฌ์ด์๋ ์๋ธ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ์ ๊ฒ์ ์ฑ๋ฅ์ด ๋๋ผ๋งํฑํ๊ฒ ๋๋น ์ง ๊ฒ์ด๋ผ๋ ํต๋ ์ด ์กด์ฌํ๋ ๊ฒ ๊ฐ๋ค.
๋ ๋ํ ๊ทธ๋ ๊ฒ ์๊ฐํด์์๋๋ฐ ์ด๊ฒ ์ ๋ง ๋ง๋์ง, ์๋๋ฉด ์คํด์ธ ๊ฒ์ธ์ง ํ์ธํด๋ณด๋ คํ๋ค.
์๋ธ ์ฟผ๋ฆฌ๋?
์๋ธ ์ฟผ๋ฆฌ๋ ๋ฉ์ธ ์ฟผ๋ฆฌ๊ฐ ์กด์ฌํ๋ ์ํฉ์์ ๋ฉ์ธ ์ฟผ๋ฆฌ ๋ด์ ํฌํจ๋ ๋ ๋ค๋ฅธ ์ฟผ๋ฆฌ๋ฅผ ์๋ฏธํ๋ค.
์ด๋ค ์ ์ ํฌํจ๋ ์ฟผ๋ฆฌ์ธ์ง์ ๋ฐ๋ผ ์ค์นผ๋ผ ์๋ธ ์ฟผ๋ฆฌ(SELECT ๋ฌธ), ์ธ๋ผ์ธ ๋ทฐ(FROM ์ ), ์๋ธ ์ฟผ๋ฆฌ(WHERE ์ , ๊ทธ๋ฅ ์๋ธ ์ฟผ๋ฆฌ๋ผ๊ณ ํ๋ ๋ฏ...) ๋ฑ์ ๋ช ์นญ์ผ๋ก ๋ถ๋ฆฐ๋ค.
์๋๋ ์๋ธ ์ฟผ๋ฆฌ์ ์์์ด๋ค.
-- ์ค์นผ๋ผ ์๋ธ ์ฟผ๋ฆฌ
SELECT
p.id AS id,
(SELECT email FROM account WHERE email = p.account) AS acc_email
FROM post p
WHERE created_at > '2024-01-20'::DATE - interval '1 MONTH';
-- ์ธ๋ผ์ธ ๋ทฐ
SELECT
p.id AS post_id,
a.email AS acc_email
FROM
account a,
(SELECT * FROM post WHERE created_at > '2024-01-20'::DATE - interval '1 MONTH') p
WHERE p.account = a.email;
-- ์๋ธ ์ฟผ๋ฆฌ (WHERE ์ )
SELECT *
FROM account
WHERE
email IN (SELECT DISTINCT post.account FROM post WHERE created_at > '2024-01-20'::DATE - interval '1 MONTH');
์๋ธ ์ฟผ๋ฆฌ์ ์ฑ๋ฅ
์ ์์์ ์๋ธ ์ฟผ๋ฆฌ๋ฅผ ๊ธฐ์ค์ผ๋ก, ์คํ ๊ณํ๊ณผ ์ฑ๋ฅ์ด ์ด๋ค์ง ํ์ธํด๋ณด๊ณ ํด๋น ์ฟผ๋ฆฌ์ ๋์์ผ๋ก ์ฌ๊ฒจ์ง๋ ์ฟผ๋ฆฌ์ ์คํ ๊ณํ๊ณผ ์ฑ๋ฅ์ ๋น๊ตํด๋ณด๋ ์์ผ๋ก ๊ธ์ ์งํํ๊ฒ ๋ค. ์ ์ฟผ๋ฆฌ๋ค์ ๋ชจ๋ ๋น์ทํ ์์ ์ ์ํํ๋ ์ฟผ๋ฆฌ์ด๊ธฐ ๋๋ฌธ์ ๊ฐ์ฅ ์์ ์๋ฆฌํ๊ณ ์๋ ์ค์นผ๋ผ ์๋ธ ์ฟผ๋ฆฌ์ ๋ํด์๋ง ํ์ธํด๋ณด๊ฒ ๋ค. ์ด ๋ ํ ์คํธ์ฉ DB๋ก๋ PostgreSQL์ ์ฌ์ฉํ์๋ค.
ํ ์คํธ ์ฌ์ ์์
ํด๋น ํ ์คํธ๋ฅผ ์ํด account ํ ์ด๋ธ๊ณผ post ํ ์ด๋ธ์ ์๋์ ์คํค๋ง๋ก ์์ฑํด์ฃผ์๊ณ , ๊ฐ๊ฐ 5๋ง๊ฐ์ 25๋ง๊ฐ์ ๋๋ฏธ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํด์ฃผ์๋ค.
CREATE TABLE account (
email VARCHAR(50) PRIMARY KEY,
pwd VARCHAR(20) NOT NULL,
created_at TIMESTAMPTZ NOT NULL
);
CREATE TABLE post (
id SERIAL PRIMARY KEY,
account VARCHAR(50) NOT NULL,
title VARCHAR(30) NOT NULL,
content VARCHAR NOT NULL,
created_at TIMESTAMPTZ NOT NULL,
CONSTRAINT fk_post_account FOREIGN KEY (account) REFERENCES account(email)
);
์ฑ๋ฅ ํ์ธ
์ ์์์ ์ฟผ๋ฆฌ๋ ์๋์ ๊ฐ๋ค.
SELECT
p.id AS id,
(SELECT email FROM account WHERE email = p.account) AS acc_email
FROM post p
WHERE created_at > '2024-01-20'::DATE - interval '1 MONTH';
ํด๋น ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์ ์๋์ ๊ฐ๋ค.

์คํ ๊ณํ์ ๋ณด๋ฉด post ํ ์ด๋ธ์ ํ์ค์บํ๋ฉด์ ์กฐ๊ฑด์ ์ ๋ถํฉํ๋ 6๋ง์ฌ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ๊ณ , ์ด๋ค์ ๋ํด ์ผ์ผ์ด account ํ ์ด๋ธ์ ์ธ๋ฑ์ค๋ฅผ ํ์ธํ๋ ๋ชจ์ต์ด๋ค. ์๋ธ ์ฟผ๋ฆฌ ์ชฝ์ 6๋ง๊ฑด์ loop ๊ฐ์ด ์ด๋ฅผ ๋งํด์ค๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด์ ์์ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ๋ฐํํ๋ ์กฐ์ธ ์ฟผ๋ฆฌ๋ฅผ ์คํ์์ผ๋ณด์. ์ฌ๊ตฌ์ฑํ ์ฟผ๋ฆฌ๋ ์๋์ ๊ฐ๋ค.
SELECT
p.id AS id,
a.email AS acc_email
FROM post p
LEFT JOIN account a
ON a.email = p.account
WHERE p.created_at > '2024-01-20'::DATE - interval '1 MONTH';
ํด๋น ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์ ์๋์ ๊ฐ๋ค.

์คํ ๊ณํ์ ๋ณด๋ฉด post ํ ์ด๋ธ์ ํ์ค์บํ์ฌ ์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ๋ค์ ์ฝ๊ณ , account ํ ์ด๋ธ์ ๋ฐ๋ก ํ์ค์บํ์ฌ ํด์ํ ์ด๋ธ์ ์์ฑํ์ฌ ์ด๋ฅผ ์ด์ฉํด์ ์กฐ์ธ์ ์ํํ๊ณ ์๋ค. ์กฐ์ธ์ ์ธ์ ๋ณ ๋ฉ๋ชจ๋ฆฌ์ ์์ฑํ ํด์ํ ์ด๋ธ์ ํตํด ์ํํ๊ธฐ ๋๋ฌธ์ ๋ฒํผ ์บ์๋ฅผ ์ฝ๋ ๋ ผ๋ฆฌ์ IO๊ฐ ํ์ฐํ ์ค์ด๋ ๊ฒ์ ์ ์ ์๋ค. (187253ํ -> 5570ํ) ๋ํ ์ค์ ์ฑ๋ฅ๋ ๋ง์ด ๊ฐ์ ๋์๋ค. (277ms ->101ms)
๊ทธ๋ ๋ค๋ฉด ํ๋ณธ์ด ๋จ ํ๋์ ์ฟผ๋ฆฌ์ด๊ธด ํ๋, ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์ถ๋ ฅํ๋ ์ฟผ๋ฆฌ์ ๋ํด ์กฐ์ธ ์ฟผ๋ฆฌ๊ฐ ํจ์ฌ ์ข์ ์ฑ๋ฅ์ด ๋ณด์ด๊ธฐ ๋๋ฌธ์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์กฐ์ธ ์ฐ์ฐ์ด ๋ ๋ซ๋ค๊ณ ์ผ๋ฐํํ ์ ์์๊น?
์ด๋ ๋ช ๋ฐฑํ ์๋๋ค. ๋ค์ ํ๋ฒ ์ ์๋ธ ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์ ์ดํด๋ณด๋ฉด, ๋งค ๋ ์ฝ๋๋ง๋ค ์๋ธ ์ฟผ๋ฆฌ๊ฐ ์คํ๋๊ณ ์๋ ๊ฒ์ ์ ์ ์๋๋ฐ ์ด๋ ์ฌ์ค NL ์กฐ์ธ๊ณผ ๋์ผํ๊ฒ ์๋ํ๊ณ ์๋ ๊ฒ์ด๋ค. ์์์ ์ดํด๋ณธ ๊ฒฝ์ฐ๋ 6๋ง๊ฑด์ด๋ ๋๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๊ธฐ ๋๋ฌธ์ ์ตํฐ๋ง์ด์ ๊ฐ ํด์ ์กฐ์ธ์ ์ ํํ๊ณ , ์ด๋ก ์ธํด ์๋ธ ์ฟผ๋ฆฌ์ ๋นํจ์จ์ด ์ปค์ก์ง๋ง ์ตํฐ๋ง์ด์ ๊ฐ NL ์กฐ์ธ์ ์ ํํ๋ ๊ฒฝ์ฐ์๋ ๋ ์ฟผ๋ฆฌ๊ฐ ์ ์ฌํ ์ฑ๋ฅ์ ๋ณด์ผ ๊ฐ๋ฅ์ฑ์ด ํฌ๋ค.
์ด ๊ฒฝ์ฐ๋ฅผ ํ์ธํ๊ธฐ ์ํด ์ ์ฟผ๋ฆฌ๋ฅผ ์๋์ฒ๋ผ ์์ ํ ๋ค ๋ค์ ํ๋ฒ ์คํ ๊ณํ์ ํ์ธํด๋ณด์.
SELECT
p.id AS id,
(SELECT email FROM account WHERE email = p.account) AS acc_email
FROM post p
WHERE created_at > '2024-01-20'::DATE - interval '6 HOUR';
SELECT
p.id AS id,
a.email AS acc_email
FROM post p
LEFT JOIN account a
ON a.email = p.account
WHERE p.created_at > '2024-01-20'::DATE - interval '6 HOUR';
๋ ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์ ๊ฐ๊ฐ ์๋์ ๊ฐ๋ค.


๋ ์ฟผ๋ฆฌ์ ์คํ ๊ณํ์ ๋น๊ตํด๋ณด๋ฉด, ๊ณ์ธต ๊ตฌ์กฐ๊ฐ ์กฐ๊ธ ๋ค๋ฅด๊ฒ ๋ณด์ผ ์๋ ์์ผ๋ ๊ฒฐ๊ตญ์ ๊ฑฐ์ ๋์ผํ๊ฒ ์๋ํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ๋ฐ๋ผ์ NL ์กฐ์ธ์ผ๋ก ์คํ๋๋ ์กฐ์ธ ์ฟผ๋ฆฌ๋ผ๋ฉด ๋ ์ฟผ๋ฆฌ์ ์ฑ๋ฅ์ ๋น์ทํ๋ค๊ณ ๋ณผ ์ ์๋ค.
๊ฒฐ๋ก
๊ฒฐ๋ก ๋ง ๋๊ณ ๋ณด์๋ฉด, ๊ฒฐ๊ตญ ๋์ผํ ์ฟผ๋ฆฌ๋ผ๋ฉด ์กฐ์ธ๋ฌธ์ผ๋ก ์์ฑ or ์ ๋๋๋๋ก ํ๋ ๊ฒ์ด ์ฑ๋ฅ ์ ์ฐจ์ ์ ๋ณด์ฅํ๋ ๋ฐฉ๋ฒ์ด ์๋๋๊ณ ํ ์ ์๊ณ , ์ด๋ ํ๋นํด๋ณด์ธ๋ค. ํ์ง๋ง ์คํดํ์ง ๋ง์์ผ ํ ์ ์ ์ด ๊ฒฝ์ฐ ์๋ธ ์ฟผ๋ฆฌ๋ผ์ ๋๋ฆฐ ๊ฒ์ด ์๋๋ผ NL ์กฐ์ธ์ด์ฌ์ ๋๋ฆฐ ๊ฒ์ด๋ค. NL ์กฐ์ธ์ ์กฐํํด์ผ ํ ๋ฐ์ดํฐ๊ฐ ๋ง์ ๊ฒฝ์ฐ ์ฑ๋ฅ ์ ๋ถ์ด์ต์ด ๋ฐ์ํ๋ ๊ตฌ์กฐ์ด๊ธฐ ๋๋ฌธ์ ์์ฐ์ ์ผ๋ก ๋ฐ์ํ๋ ์ฑ๋ฅ ์ ํ์ด๊ณ , ์ตํฐ๋ง์ด์ ๊ฐ ์๋ธ ์ฟผ๋ฆฌ๋ฅผ unnest ์ฒ๋ฆฌํ์ฌ ๋ค๋ฅธ ์กฐ์ธ ๋ฐฉ์์ผ๋ก ํ์ง ์๋ ์ด์ NL ์กฐ์ธ์ ๊ตฌ์กฐ๋ฅผ ํํผํ๋ ๊ฒ์ ์ด๋ ต๋ค.
๊ฒฐ๋ก ์ด ์ข ๊ธธ์ด์ก๋๋ฐ, ํ๊ณ ์ถ์ ์ด์ผ๊ธฐ๋ ๊ฒฐ๊ตญ ์ ์๋ธ ์ฟผ๋ฆฌ๊ฐ ์ฑ๋ฅ์ด ๋ ์์ข์ ๊ฒ์ธ์ง ์ ๋๋ก ํ์ ํ์ง ์๊ณ ๋ฌด์กฐ๊ฑด ์๋ธ ์ฟผ๋ฆฌ๋ผ์ ์์ข๋ค๋ ๊ฒ์ ๊ทธ ์ฌ๋์ ์ฐฉ๊ฐ์ด๋ผ๋ ๊ฒ์ด๋ค. ์ด๊ฑด ๊ฒฐ๊ตญ ๊น๋๊ณ ๋ณด๋ฉด NL ์กฐ์ธ์ ํด์ ์กฐ์ธ๋ณด๋ค ํญ์ ์ฑ๋ฅ์ด ์์ข๋ค! ๋ผ๊ณ ๋งํ๋ ๊ฒ๊ณผ ๋ค๋ฅด์ง ์๋ค.
์ฌ๋ด
์ค๋ผํด์๋ ์ค์นผ๋ผ ์๋ธ ์ฟผ๋ฆฌ ์บ์ฑ์ด๋ผ๋ ๊ธฐ๋ฅ์ด ์กด์ฌํ๋ค. PGA ์์ญ์ ์ค์นผ๋ผ ์๋ธ ์ฟผ๋ฆฌ์ ๋ํด input -> output์ ์บ์ฑํด๋๊ณ ๋์ผํ input์ด ๋ค์ด์ค๋ ๊ฒฝ์ฐ ๋ฒํผ ์บ์๋ฅผ ์กฐํํ์ง ์๊ณ ๊ณง๋ฐ๋ก output์ ๋์ถํ๋ ์์ผ๋ก ์๋ํ๋ค. ๋ฐ๋ผ์ ๋ณธ๋ฌธ์์ ์ธ๊ธํ NL ์กฐ์ธ ์์์ ๊ฒฝ์ฐ, ์คํ๋ ค ์๋ธ ์ฟผ๋ฆฌ ์์ ๊ฐ ์ฑ๋ฅ ์ ๋ ๋์ ์๋ ์๋ค. ๋ณธ๋ฌธ์ ์์๋ Postgresql์ ์ฌ์ฉํ์๊ธฐ ๋๋ฌธ์ ์ด์๋ ์ ์ฌํ ๊ธฐ๋ฅ์ด ์๋ ์ฐพ์๋ดค๋๋ฐ, ์๋ฃ๊ฐ ๋ง์ด ๋์ค์ง ์์์ผ๋ ์๋ ์ํฐํด์ ๋ณด๋ฉด ์ ์ฌํ ๊ธฐ๋ฅ์ด ํ์ฌ๋ ์กด์ฌํ๋ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
์ปค๋ฎค๋ํฐ > ๋๋ง์ ๊ฐ์ข๋ฐ ํ > Scalar subquery caching and Memoization1 - All About PostgreSQL
์ด ๊ฒ์๋ฌผ 159๊ฑด, ์ต๊ทผ 0 ๊ฑด Scalar subquery caching and Memoization1 ๊ธ์ด์ด : ๋ชจ๋ธ๊ด ๋ ์ง : 2022-02-05 (ํ ) 10:44 ์กฐํ : 1657 In the last article titled Scalar Subquery Optimization I mentioned that some scalar subqueries in PostgreSQL ha
www.postgresdba.com
์ปค๋ฎค๋ํฐ > ๋๋ง์ ๊ฐ์ข๋ฐ ํ > Scalar subquery caching and Memoization2 - All About PostgreSQL
์ด ๊ฒ์๋ฌผ 159๊ฑด, ์ต๊ทผ 0 ๊ฑด Scalar subquery caching and Memoization2 ๊ธ์ด์ด : ๋ชจ๋ธ๊ด ๋ ์ง : 2022-02-05 (ํ ) 10:45 ์กฐํ : 1322 As expected the execution plan now tells us that Sort operation completed inside a view called v1; and we can se
www.postgresdba.com
'Database > DB ์คํฐ๋' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
MVCC in Mysql(with ํธ๋์ญ์ ๊ฒฉ๋ฆฌ์์ค) (0) | 2024.02.25 |
---|---|
Exists ์ฐ์ฐ์์ ๋ํด์ (SQL) (0) | 2024.02.12 |
SGA vs PGA (in Oracle) (1) | 2024.01.14 |
๋ณตํฉ ์ธ๋ฑ์ค ํ์ฉ ๊ฒฝ์ฐ์ ์ (1) | 2023.12.31 |
๋ฑํธ ์ฐ์ฐ์์ LIKE ์ฐ์ฐ์ ๊ฐ ๋น๊ต (1) | 2023.12.17 |