๐Ÿ› ๏ธAI ๋„๊ตฌ2026-01-28

B-Tree ์ธ๋ฑ์Šค๋งŒ ์“ฐ์‹œ๋‚˜์š”

๐Ÿ’ก ํ•œ์ค„ ์š”์•ฝ|B-Tree ์ธ๋ฑ์Šค๋งŒ ์“ฐ์‹œ๋‚˜์š”? ์ฒดํฌ ์ œ์•ฝ์กฐ๊ฑด์œผ๋กœ ํ’€ ์Šค์บ”์„ ํ”ผํ•˜๊ณ , Hash ์ธ๋ฑ์Šค๋กœ ์œ ๋‹ˆํฌ ์ œ์•ฝ์กฐ๊ฑด์„ ๊ฑธ์–ด ์ธ๋ฑ์Šค ํฌ๊ธฐ๋ฅผ 1/5๋กœ ์ค„์ด๋Š” ์‹ค์ „ ํ…Œํฌ๋‹‰.

Source: Unconventional PostgreSQL Optimizations

๐ŸŽฃ Hook: "์ธ๋ฑ์Šค ๊ฑธ์—ˆ๋Š”๋ฐ ์™œ ๋А๋ฆฌ์ฃ ?"

์ฟผ๋ฆฌ ํŠœ๋‹์€ ์˜ˆ์ˆ ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋•Œ๋กœ๋Š” ์ •์„์ ์ธ ๋ฐฉ๋ฒ•(B-Tree ์ธ๋ฑ์Šค ์ถ”๊ฐ€)๋งŒ์œผ๋กœ๋Š” ํ•œ๊ณ„์— ๋ถ€๋”ชํž™๋‹ˆ๋‹ค. ์ธ๋ฑ์Šค ํฌ๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ์ปค์ ธ์„œ ์˜คํžˆ๋ ค ์„ฑ๋Šฅ์„ ๊ฐ‰์•„๋จน๊ธฐ๋„ ํ•˜์ฃ .

์—ฌ๊ธฐ, Haki Benita๊ฐ€ ์ œ์•ˆํ•˜๋Š” "๋น„์ƒ์‹์ ์ด์ง€๋งŒ ํšจ๊ณผ์ ์ธ" ์ตœ์ ํ™” ๋ฐฉ๋ฒ• 3๊ฐ€์ง€๋ฅผ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ The Techniques

1. ์ฒดํฌ ์ œ์•ฝ์กฐ๊ฑด(Check Constraints)์œผ๋กœ ํ’€ ์Šค์บ” ํ”ผํ•˜๊ธฐ

๊ฐœ๋ฐœ์ž์˜ ์‹ค์ˆ˜๋กœ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฐ’์„ ์กฐํšŒํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. (์˜ˆ: plan='Pro'์ธ๋ฐ ์‹ค์ œ๋กœ๋Š” plan='pro'๋กœ ์ €์žฅ๋จ) ๋ณดํ†ต์€ DB๊ฐ€ ๋ฐ”๋ณด์ฒ˜๋Ÿผ ํ…Œ์ด๋ธ”์„ ๋‹ค ๋’ค์ง‘๋‹ˆ๋‹ค(Full Scan). ํ•˜์ง€๋งŒ Check Constraint๋ฅผ ๊ฑธ์–ด๋‘๋ฉด?

ALTER TABLE users ADD CONSTRAINT check_plan CHECK (plan IN ('free', 'enterprise', 'pro'));
-- ๊ทธ๋ฆฌ๊ณ  ์„ค์ • ์ผœ๊ธฐ
SET constraint_exclusion = on;

์ด์ œ DB๋Š” plan='Pro' ์ฟผ๋ฆฌ๊ฐ€ ์˜ค๋ฉด "์–ด? ์ œ์•ฝ์กฐ๊ฑด์— ์—†๋„ค?" ํ•˜๊ณ  ๊ฒ€์ƒ‰ ์ž์ฒด๋ฅผ ์‹œ๋„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(0ms).

2. ํ•จ์ˆ˜ ๊ธฐ๋ฐ˜ ์ธ๋ฑ์Šค๋กœ ๋‹ค์ด์–ดํŠธํ•˜๊ธฐ

created_at ๊ฐ™์€ ํƒ€์ž„์Šคํƒฌํ”„ ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค๋ฅผ ๊ฑธ๋ฉด ํฌ๊ธฐ๊ฐ€ ์—„์ฒญ๋‚ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ์กฐํšŒ๋Š” '๋‚ ์งœ(Day)' ๋‹จ์œ„๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค๋ฉด?

-- ์ „์ฒด ํƒ€์ž„์Šคํƒฌํ”„ ๋Œ€์‹  ๋‚ ์งœ๋งŒ ์ธ๋ฑ์‹ฑ
CREATE INDEX idx_sold_at_date ON sales ((date_trunc('day', sold_at AT TIME ZONE 'UTC')));

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ธ๋ฑ์Šค ํฌ๊ธฐ๊ฐ€ 3๋ฐฐ ์ด์ƒ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค. PG ์—”์ง„์ด ์ค‘๋ณต๋œ ๋‚ ์งœ ๊ฐ’๋“ค์„ ์••์ถ•(Deduplication)ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

3. Hash ์ธ๋ฑ์Šค๋กœ ์œ ๋‹ˆํฌ(Unique) ๊ฑธ๊ธฐ

"URL ๊ฐ™์€ ๊ธด ๋ฌธ์ž์—ด์˜ ์ค‘๋ณต์„ ๋ง‰๊ณ  ์‹ถ๋‹ค." ๋ณดํ†ต UNIQUE ์ œ์•ฝ์กฐ๊ฑด์„ ๊ฑธ๋ฉด B-Tree ์ธ๋ฑ์Šค๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ URL์€ ๋„ˆ๋ฌด ๊ธธ์–ด์„œ ์ธ๋ฑ์Šค ์šฉ๋Ÿ‰์„ ๋งŽ์ด ์ฐจ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์ด๋•Œ Hash Index๋ฅผ ์“ฐ๋ฉด ํš๊ธฐ์ ์œผ๋กœ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (B-Tree ๋Œ€๋น„ 5๋ฐฐ ์ž‘์Œ)

-- Exclude Constraint๋ฅผ ์ด์šฉํ•œ ํ•ด์‹œ ์œ ๋‹ˆํฌ
ALTER TABLE urls ADD CONSTRAINT urls_unique_hash EXCLUDE USING HASH (url WITH =);

์ด์ œ URL ์ž์ฒด๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ํ•ด์‹œ๊ฐ’๋งŒ ์ €์žฅํ•˜๋ฏ€๋กœ ์šฉ๋Ÿ‰์ด ํš๊ธฐ์ ์œผ๋กœ ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.

MAX5์˜ ์ƒ๊ฐ ๐ŸŽฏ

๐Ÿ‘จโ€๐Ÿ’ป ๋ฐ”์ด๋ธŒ ์ฝ”๋”ฉ ๋ ˆ์‹œํ”ผ

๋‚ด DB ์Šคํ‚ค๋งˆ๋ฅผ ๋˜์ ธ์ฃผ๊ณ  "๋น„์ƒ์‹์ ์ธ ์ตœ์ ํ™”"๋ฅผ ๋งก๊ฒจ๋ณด์ž. "์ด ํ…Œ์ด๋ธ” ์Šคํ‚ค๋งˆ(CREATE TABLE...)๋ฅผ ๋ด์ค˜. URL ์ปฌ๋Ÿผ์ด ์žˆ๋Š”๋ฐ ์ค‘๋ณต ๋ฐฉ์ง€๊ฐ€ ํ•„์š”ํ•ด. B-Tree ์ธ๋ฑ์Šค ๋Œ€์‹  Hash ์ธ๋ฑ์Šค๋กœ ์ตœ์ ํ™”ํ•˜๋Š” SQL ์ฟผ๋ฆฌ๋ฅผ ์งœ์ฃผ๊ณ , ์žฅ๋‹จ์ ์„ ์„ค๋ช…ํ•ด์ค˜."

๐Ÿ’ธ ์‚ฌ์ด๋“œ ํ”„๋กœ์ ํŠธ ์•„์ด๋””์–ด

"Unconventional Linter": pg_dump ์Šคํ‚ค๋งˆ ํŒŒ์ผ์„ ๋„ฃ์œผ๋ฉด, ์ด๋Ÿฐ '๋ณ€ํƒœ์ ์ธ' ์ตœ์ ํ™” ํŒ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ปฌ๋Ÿผ์„ ์ฐพ์•„์„œ ์ œ์•ˆํ•ด์ฃผ๋Š” CI/CD ๋„๊ตฌ. (Check Constraints ํ™œ์šฉ ๊ธฐํšŒ ํฌ์ฐฉ ๋“ฑ)


์นดํ…Œ๊ณ ๋ฆฌ: tech_deep_dive, ``

์ด ๊ธ€์ด ์–ด๋• ๋‚˜์š”?