๐งฉ 1. ์ง์ฐ ์ฟผ๋ฆฌ(Delayed Query)๋?
PostgreSQL์์ ์ง์ฐ ์ฟผ๋ฆฌ๋ ์ผ๋ฐ์ ์ผ๋ก ์ฟผ๋ฆฌ ์คํ์ด ์ฆ์ ์ํ๋์ง ์๊ณ , ๊ฒฐ๊ณผ๊ฐ ํ์ํ ๋ ์ค์ ์คํ์ด ์ด๋ค์ง๋ ํํ๋ฅผ ๋งํฉ๋๋ค.
์ฆ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ง์ด ๊ฐ๋ฅํ ํ Lazy Execution(์ง์ฐ ์คํ) ์ ๋ต์ ์ฌ์ฉํด ๋ถํ์ํ ์ฐ์ฐ์ ์ค์ด๋ ๋ฐฉ์์
๋๋ค.
๋ํ์ ์ธ ์์๋ ๋ทฐ(View) ๋๋ CTE(Common Table Expression) ์
๋๋ค.
์๋ฅผ ๋ค์ด, ์๋ ์ฟผ๋ฆฌ๋ฅผ ๋ณด๊ฒ ์ต๋๋ค.
WITH user_data AS (
SELECT * FROM users WHERE is_active = true
)
SELECT * FROM user_data WHERE age > 30;
์ด๋ PostgreSQL์ user_data๋ฅผ ์ค์ ํ
์ด๋ธ์ฒ๋ผ ์ฆ์ ์์ฑํ์ง ์์ต๋๋ค.
๋์ ์ต์ข
SELECT๊ฐ ์คํ๋ ๋๊น์ง ๋ด๋ถ์ ์ผ๋ก ์ง์ฐ์์ผ, ํ์ํ ๋ถ๋ถ๋ง ์คํํ๋๋ก ์ต์ ํํฉ๋๋ค.
์ด๊ฒ์ด ๋ฐ๋ก ์ง์ฐ ์ฟผ๋ฆฌ์ ํต์ฌ ๊ฐ๋
์
๋๋ค โ “ํ์ํ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค.”
โ๏ธ ์ง์ฐ ์ฟผ๋ฆฌ์ ์ฅ์
- ๋ถํ์ํ I/O๋ฅผ ์ค์ผ ์ ์์
- ์กฐ์ธ๊ณผ ํํฐ ์กฐ๊ฑด์ด ํฉ์ณ์ ธ ์คํ ๊ณํ์ด ๋ ํจ์จ์ ์ผ ์ ์์
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋ ๊ฐ์
โ ๏ธ ๋จ์
- ๋ณต์กํ ์๋ธ์ฟผ๋ฆฌ ๊ตฌ์กฐ์์๋ ์คํ ๊ณํ์ด ์์ธกํ๊ธฐ ์ด๋ ค์
- ์ค๋ณต ์ฐ์ฐ์ด ๋ง์์ง ๊ฒฝ์ฐ, ์์์น ๋ชปํ ์ฑ๋ฅ ์ ํ ๊ฐ๋ฅ
๐งฑ 2. ๊ณตํต ์ฟผ๋ฆฌ(Common Query)๋?
๊ณตํต ์ฟผ๋ฆฌ๋ ๊ฐ๋ฐ ์ ์ฌ๋ฌ ์๋น์ค๋ ๋ชจ๋์์ ์ฌ์ฌ์ฉํ ์ ์๋ ์ฟผ๋ฆฌ ๋ก์ง์ ๋ณ๋๋ก ์ ์ํ ๊ฒ์ ์๋ฏธํฉ๋๋ค.
์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์กฐํํ๋ ๊ณตํต ์ฟผ๋ฆฌ๋ฅผ ์๋์ฒ๋ผ ํ๋์ SQL ํจ์๋ View๋ก ๋ง๋ค์ด๋๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
CREATE VIEW active_user_info AS
SELECT id, name, email
FROM users
WHERE is_active = true;
์ด์ ๋ชจ๋ ์๋น์ค์์๋ ๋ค์๊ณผ ๊ฐ์ด ๊ฐ๋จํ๊ฒ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค.
SELECT * FROM active_user_info WHERE age > 30;
์ด์ฒ๋ผ ์ฝ๋ ์ค๋ณต์ ์ค์ด๊ณ , ๋ก์ง ์ผ๊ด์ฑ์ ์ ์งํ ์ ์๋ ์ ์ด ๊ณตํต ์ฟผ๋ฆฌ์ ํฐ ์ฅ์ ์ ๋๋ค.
โก 3. ํ์ง๋งโฆ ๊ณตํต ์ฟผ๋ฆฌ๋ ์ฑ๋ฅ์ ๋ฐ๋์ ๊ณ ๋ คํด์ผ ํ๋ค
๋ง์ ๊ฐ๋ฐ์๊ฐ โ๊ณตํต ์ฟผ๋ฆฌ = ํจ์จ์ ์ธ ์ฝ๋โ ๋ผ๊ณ ์ฐฉ๊ฐํ์ง๋ง, ๋ฐ์ดํฐ๋ฒ ์ด์ค์์๋ ์ํฉ์ด ๋ค๋ฆ
๋๋ค.
๊ณตํต ์ฟผ๋ฆฌ๋ฅผ ์๋ชป ์ค๊ณํ๋ฉด ์คํ๋ ค ์ฑ๋ฅ์ด ์ฌ๊ฐํ๊ฒ ์ ํ๋ ์ ์์ต๋๋ค.
๐ง ์๋ฅผ ๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
CREATE VIEW common_order_data AS
SELECT
o.id,
o.user_id,
u.name,
o.total_price,
o.created_at
FROM orders o
JOIN users u ON u.id = o.user_id;
์ด ์ฟผ๋ฆฌ๋ฅผ ์ฌ๋ฌ ์๋น์ค์์ ์ฌ์ฌ์ฉํ๋ค๊ณ ๊ฐ์ ํด๋ด
์๋ค.
ํ์ง๋ง ์ผ๋ถ ์๋น์ค์์๋ user_id๋ง ํ์ํ๊ณ , ๋ค๋ฅธ ์๋น์ค๋ created_at์ผ๋ก ์ ๋ ฌ๋ง ํฉ๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก PostgreSQL์ ๋งค๋ฒ ์ ์ฒด JOIN์ ๋ค์ ์ํํ๊ฒ ๋๋ฉฐ,
์ค์ ํ์ํ ๋ฐ์ดํฐ๋ณด๋ค ํจ์ฌ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ ๋ ฌํ๋ ๋นํจ์จ์ด ๋ฐ์ํฉ๋๋ค.
์ฆ, ๊ณตํต ์ฟผ๋ฆฌ์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ง๋ง, ์คํ ๊ณํ์ ๋นํจ์จ์ ์ด ๋ ์ ์์ต๋๋ค.
๐งญ 4. ๊ณตํต ์ฟผ๋ฆฌ๋ฅผ ์ค๊ณํ ๋ ๊ณ ๋ คํด์ผ ํ ์ฌํญ
| ํญ๋ชฉ | ์ค๋ช | ์์ |
|---|---|---|
| ์คํ ๊ณํ (EXPLAIN ๋ถ์) | ๊ณตํต ์ฟผ๋ฆฌ ์คํ ์ ์ค์ ๋น์ฉ์ ๋ฐ๋์ ํ์ธํด์ผ ํจ | EXPLAIN ANALYZE SELECT * FROM common_order_data; |
| ํ์ํ ์ปฌ๋ผ๋ง SELECT | ์ฌ์ฉํ์ง ์๋ ์ปฌ๋ผ๊น์ง ์กฐํํ๋ฉด ๋ถํ์ํ I/O ๋ฐ์ | SELECT id, name ๋ง ํ์ํ๋ค๋ฉด ๊ทธ๊ฒ๋ง ์กฐํ |
| ์กฐ๊ฑด์ ์ธ๋ถ์์ ๋ฐ๋๋ก ์ค๊ณ | ๊ณตํต ์ฟผ๋ฆฌ ๋ด๋ถ์์ WHERE ์กฐ๊ฑด์ ๊ณ ์ ํ์ง ๋ง ๊ฒ | WHERE is_active = :is_active |
| ์ธ๋ฑ์ค ๊ณ ๋ ค | ๊ณตํต ์ฟผ๋ฆฌ ๋์ ์ปฌ๋ผ์ ์ ์ ํ ์ธ๋ฑ์ค ์์ฑ | CREATE INDEX idx_users_is_active ON users(is_active); |
| ์บ์ ํ์ฉ | ์์ฃผ ์กฐํ๋๋ ๊ณตํต ์ฟผ๋ฆฌ๋ Redis ๋ฑ ์บ์ ์ฌ์ฉ ๊ฒํ | ์ค์๊ฐ์ฑ์ด ๋ฎ์ ๋ฐ์ดํฐ๋ผ๋ฉด ์บ์ฑ ๊ณ ๋ ค |
๐งฉ 5. ๋ง๋ฌด๋ฆฌ โ ์ฌ์ฌ์ฉ๋ณด๋ค ์ค์ํ ๊ฑด โ์คํ ํจ์จ์ฑโ
PostgreSQL์์ ๊ณตํต ์ฟผ๋ฆฌ๋ ์ ์ง๋ณด์์ฑ๊ณผ ์ผ๊ด์ฑ ์ธก๋ฉด์์๋ ๋งค์ฐ ์ ์ฉํ์ง๋ง,
๋ชจ๋ ์ํฉ์ ์ ํฉํ ์ ๋ต์ ์๋๋๋ค.
ํนํ ๋๊ท๋ชจ ํธ๋ํฝ์ด๋ ๋ณต์กํ ์กฐ์ธ ํ๊ฒฝ์์๋
โ๊ณตํต ์ฟผ๋ฆฌ๊ฐ ์๋๋ผ, ์๋น์ค๋ณ ์ต์ ํ ์ฟผ๋ฆฌโ๊ฐ ๋ ์ข์ ์ ํ์ด ๋ ์๋ ์์ต๋๋ค.
โ ํต์ฌ ์์ฝ
- ์ง์ฐ ์ฟผ๋ฆฌ๋ ์คํ ํจ์จ์ ๋์ด๋ PostgreSQL์ ๋ด๋ถ ์ ๋ต์ด๋ค.
- ๊ณตํต ์ฟผ๋ฆฌ๋ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด์ง๋ง, ์ฑ๋ฅ ๋ถํ๋ฅผ ์ผ๊ธฐํ ์ ์๋ค.
- ๊ณตํต ์ฟผ๋ฆฌ๋ ๋ฐ๋์
EXPLAIN ANALYZE๋ก ์คํ ๊ณํ์ ๊ฒ์ฆํด์ผ ํ๋ค.
โ๏ธ ๊ฒฐ๋ก
๊ณตํต ์ฟผ๋ฆฌ๋ ๊ฐ๋ฐ์ ํธ๋ฆฌํจ์ ์ฃผ์ง๋ง,
โ์ฑ๋ฅ์ ๋ชจ๋ฅด๋ ๊ณตํต ์ฟผ๋ฆฌโ๋ ์คํ๋ ค ๋
์ด ๋ ์ ์์ต๋๋ค.
PostgreSQL์ ์คํ ๊ณํ์ ์ดํดํ๊ณ ,
๊ณตํต ์ฟผ๋ฆฌ๋ฅผ โํจ๊ป ์ฐ๋, ์ํฉ์ ๋ง๊ฒ ์กฐ์ ํ ์ ์๋ ์ ์ฐ์ฑโ์ ๊ฐ์ง๋ ๊ฒ์ด
์ง์ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ต์ ํ์ ์์์
๋๋ค.

๋๊ธ ๋จ๊ธฐ๊ธฐ