devpia.net

๐Ÿ˜ "์ฟผ๋ฆฌ๊ฐ€ ์™œ ์ด๋ ‡๊ฒŒ ๋А๋ ค์š”?" ์‹œ๋‹ˆ์–ด๊ฐ€ ๊นŒ๋ฐœ๋ฆฌ๋Š” PostgreSQL ์ธ๋ฑ์Šค ํŠœ๋‹ & ์‹คํ–‰๊ณ„ํš ์™„๋ฒฝ ์ •๋ณต๊ธฐ!

EXPLAIN ANALYZE ๋ฒ„ํผ ๋ถ„์„๋ถ€ํ„ฐ PartialยทCovering ์ธ๋ฑ์Šค, 5์ดˆ์งœ๋ฆฌ ์ฟผ๋ฆฌ๋ฅผ 3ms๋กœ ์ค„์ด๋Š” ์‹ค์ „ ์ตœ์ ํ™” ๋น„๋ฒ• ๋Œ€๊ณต๊ฐœ

๋•์ฒ ์ด
2026๋…„ 8์›” 19์ผ ยท 13๋ถ„ ์ฝ๊ธฐ
์กฐํšŒ์ˆ˜ 1
๐Ÿ˜ "์ฟผ๋ฆฌ๊ฐ€ ์™œ ์ด๋ ‡๊ฒŒ ๋А๋ ค์š”?" ์‹œ๋‹ˆ์–ด๊ฐ€ ๊นŒ๋ฐœ๋ฆฌ๋Š” PostgreSQL ์ธ๋ฑ์Šค ํŠœ๋‹ & ์‹คํ–‰๊ณ„ํš ์™„๋ฒฝ ์ •๋ณต๊ธฐ!
โฑ๏ธ ์ฝ๋Š” ์‹œ๊ฐ„: ์•ฝ 9๋ถ„ยท์•ฝ 4,541์ž

์ƒˆ๋ฒฝ 2์‹œ, ์Šฌ๋ž™ ์•Œ๋ฆผ์Œ์ด ์š”๋ž€ํ•˜๊ฒŒ ์šธ๋ฆฝ๋‹ˆ๋‹ค. "์„ ๋ฐฐ๋‹˜, DB CPU ์‚ฌ์šฉ๋ฅ ์ด 99%๋ฅผ ์ฐ๊ณ  API ์‘๋‹ต์ด ํ„ฐ์กŒ์–ด์š”!" ์‹์€๋•€์„ ํ˜๋ฆฌ๋ฉฐ ์กธ๋ฆฐ ๋ˆˆ์„ ๋น„๋น„๋˜ ์ฃผ๋‹ˆ์–ด ์‹œ์ ˆ, ๋ˆ„๊ตฌ๋‚˜ ํ•œ ๋ฒˆ์ฏค ๊ฒช์–ด๋ณธ ์•…๋ชฝ์ด์ฃ . ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋ป—์—ˆ์„ ๋•Œ ๋ฌด์ž‘์ • ์ธ๋ฑ์Šค๋งŒ ๋•์ง€๋•์ง€ ๋ถ™์ด๋‹ค๊ฐ€ ์˜คํžˆ๋ ค ์“ฐ๊ธฐ(INSERT/UPDATE) ์„ฑ๋Šฅ๊นŒ์ง€ ๋ง์•„๋จน์€ ์  ์—†์œผ์‹ ๊ฐ€์š”? ์˜ค๋Š˜์€ ์ˆ˜๋งŽ์€ ํ”„๋กœ๋•์…˜ ์žฅ์• ๋ฅผ ์ˆ˜์Šตํ•˜๋ฉฐ ๋ผˆ์— ์ƒˆ๊ธด PostgreSQL ์ธ๋ฑ์Šค ํŠœ๋‹ ๋ฐ ์‹คํ–‰๊ณ„ํš(Execution Plan) ์™„๋ฒฝ ํ•ด๋ถ€ ํŒ์„ ์•„๋‚Œ์—†์ด ๋ฐฉ์ถœํ•ด ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„œ๋ฒ„ ๋ฐ ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ฝ˜์…‰ํŠธ
โ–ฒ DB ๋ณ‘๋ชฉ์˜ 90%๋Š” ์ž˜๋ชป๋œ ์‹คํ–‰๊ณ„ํš๊ณผ ๋น„ํšจ์œจ์ ์ธ ์ธ๋ฑ์Šค ์„ค๊ณ„์—์„œ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

1. ๋งน๋ชฉ์ ์ธ EXPLAIN์€ ๋ฒ„๋ ค๋ผ: `EXPLAIN (ANALYZE, BUFFERS)`๊ฐ€ ์ง„์งœ์ธ ์ด์œ 

๋งŽ์€ ๋ถ„๋“ค์ด ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋ฅผ ํ•  ๋•Œ ๋‹จ์ˆœํžˆ EXPLAIN๋งŒ ์น˜๊ณ  ๋๋ƒ…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ EXPLAIN๋งŒ ์“ฐ๋ฉด ์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ ์ถ”์ •ํ•œ '์˜ˆ์ƒ ๋น„์šฉ(Cost)'๋งŒ ๋ณด์—ฌ์ค„ ๋ฟ, ์‹ค์ œ ์‹คํ–‰๋œ ๊ฒฐ๊ณผ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ”„๋กœ๋•์…˜ ํŠœ๋‹์—์„œ ๋ฐ˜๋“œ์‹œ ์จ์•ผ ํ•˜๋Š” ๋ฌด๊ธฐ๋Š” ๋ฐ”๋กœ EXPLAIN (ANALYZE, BUFFERS)์ž…๋‹ˆ๋‹ค.

-- ๋‹จ์ˆœ ์ถ”์ •์น˜๊ฐ€ ์•„๋‹Œ ์‹ค์ œ ์‹คํ–‰ ์‹œ๊ฐ„๊ณผ I/O ๋ฉ”๋ชจ๋ฆฌ ๋ฒ„ํผ ์ƒํƒœ๊นŒ์ง€ ํ™•์ธ
EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS)
SELECT user_id, order_date, total_amount 
FROM orders 
WHERE created_at >= '2026-01-01' 
  AND status = 'COMPLETED';

์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๊ฐ€ ์ง‘์ค‘ํ•ด์„œ ๋œฏ์–ด๋ด์•ผ ํ•  ํ•ต์‹ฌ ์ง€ํ‘œ๋Š” ์„ธ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

  • Actual Time: (actual time=0.045..1.230 rows=150 loops=1) ํ˜•ํƒœ๋กœ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ์•ž ์ˆซ์ž๋Š” ์ฒซ ํ–‰์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„(ms), ๋’ค ์ˆซ์ž๋Š” ๋ชจ๋“  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.
  • Rows Removed by Filter: ์ธ๋ฑ์Šค๋ฅผ ํƒ”๋”๋ผ๋„ ํ•„ํ„ฐ๋ง ๊ณผ์ •์—์„œ ๋ฒ„๋ ค์ง„ ํ–‰์ด ์ˆ˜์‹ญ๋งŒ ๊ฑด์ด๋ผ๋ฉด, ๋ณตํ•ฉ ์ธ๋ฑ์Šค(Composite Index) ์ปฌ๋Ÿผ ์ˆœ์„œ๊ฐ€ ์ž˜๋ชป๋˜์—ˆ๊ฑฐ๋‚˜ ์ธ๋ฑ์Šค ์กฐ๊ฑด์ด ์—‰์„ฑํ•˜๋‹ค๋Š” ๊ฐ•๋ ฅํ•œ ์‹ ํ˜ธ์ž…๋‹ˆ๋‹ค!
  • Buffers (Shared Hit vs Read): Buffers: shared hit=420 read=15์—์„œ hit์€ ๊ณต์œ  ๋ฉ”๋ชจ๋ฆฌ(์บ์‹œ)์—์„œ ๊ฐ€์ ธ์˜จ ๋ธ”๋ก ์ˆ˜์ด๊ณ , read๋Š” ๋””์Šคํฌ I/O๋ฅผ ์ง์ ‘ ๋ฐœ์ƒ์‹œํ‚จ ๋ธ”๋ก ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋””์Šคํฌ Read ๋น„์œจ์ด ๋†’์„์ˆ˜๋ก I/O ๋ณ‘๋ชฉ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์‹œ๋‹ˆ์–ด์˜ ์‹ค๋ฌด ๊ฟ€ํŒ: Costs ์ˆ˜์น˜์— ํ˜„ํ˜น๋˜์ง€ ๋งˆ์„ธ์š”!

Cost๋Š” PostgreSQL ์˜ตํ‹ฐ๋งˆ์ด์ € ๋‚ด๋ถ€์˜ '์ƒ๋Œ€์  ์—ฐ์‚ฐ ์ ์ˆ˜'์ผ ๋ฟ ์‹ค์ œ ๊ฑธ๋ฆฐ ๋ฐ€๋ฆฌ์ดˆ(ms) ๋‹จ์œ„ ์‹œ๊ฐ„์ด ์•„๋‹™๋‹ˆ๋‹ค. Cost๊ฐ€ ๋‚ฎ์•„๋„ ๋””์Šคํฌ I/O๊ฐ€ ํญ๋ฐœํ•˜๋ฉด ์ฟผ๋ฆฌ๋Š” ๊ธฐ์–ด๊ฐ‘๋‹ˆ๋‹ค. ์–ธ์ œ๋‚˜ Actual Total Time๊ณผ Buffers: shared read ์ˆ˜์น˜๋ฅผ 0์— ๊ฐ€๊น๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ 1์ˆœ์œ„ ๋ชฉํ‘œ๋กœ ์‚ผ์œผ์„ธ์š”.

2. ์ƒํ™ฉ๋ณ„๋กœ ๊ณจ๋ผ ์“ฐ๋Š” PostgreSQL ์ธ๋ฑ์Šค ๋ฌด๊ธฐ์ฐฝ๊ณ 

ํ”ํžˆ ์ธ๋ฑ์Šค๋ผ๊ณ  ํ•˜๋ฉด B-Tree๋งŒ ๋– ์˜ฌ๋ฆฌ์‹œ์ฃ ? ํ•˜์ง€๋งŒ PostgreSQL์€ ์ƒ์ƒ ์ด์ƒ์œผ๋กœ ๋˜‘๋˜‘ํ•˜๊ณ  ๋‹ค์–‘ํ•œ ์ธ๋ฑ์Šค ์—”์ง„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ํŠน์„ฑ์— ๋งž์ถฐ ์ œ๋Œ€๋กœ ๋œ ์ธ๋ฑ์Šค๋ฅผ ๊ฝ‚์•„์ฃผ๋ฉด ๋“œ๋ผ๋งˆํ‹ฑํ•œ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ๊ฒฝํ—˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธ๋ฑ์Šค ๊ตฌ์กฐ์™€ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ตœ์ ํ™” ์ฝ”๋“œ
โ–ฒ ๋ฐ์ดํ„ฐ์˜ ์นด๋””๋„๋ฆฌํ‹ฐ์™€ ์ฟผ๋ฆฌ ํŒจํ„ด์— ๋งž๋Š” ์ตœ์ ์˜ ์ธ๋ฑ์Šค๋ฅผ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

โ‘  ๋ถ€๋ถ„ ์ธ๋ฑ์Šค (Partial Index) โ€“ ์šฉ๋Ÿ‰์€ ์ค„์ด๊ณ  ์†๋„๋Š” ๊ทน๋Œ€ํ™”!

์†Œํ”„ํŠธ ๋”œ๋ฆฌํŠธ(Soft Delete)๋‚˜ ํŠน์ • ์ƒํƒœ๊ฐ’(์˜ˆ: status = 'PENDING')์ฒ˜๋Ÿผ ์ „์ฒด ๋ฐ์ดํ„ฐ ์ค‘ 5~10% ๋ฏธ๋งŒ์˜ ํŠน์ • ๋ ˆ์ฝ”๋“œ๋งŒ ์ž์ฃผ ์กฐํšŒํ•œ๋‹ค๋ฉด ์ „์ฒด ํ–‰์„ ์ธ๋ฑ์‹ฑํ•  ์ด์œ ๊ฐ€ ์ „ํ˜€ ์—†์Šต๋‹ˆ๋‹ค.

-- [AS-IS] 1,000๋งŒ ๊ฑด ์ „์ฒด์— ์ธ๋ฑ์Šค ์ƒ์„ฑ (์šฉ๋Ÿ‰ ์ˆ˜๋ฐฑ MB ๋‚ญ๋น„, CUD ์„ฑ๋Šฅ ์ €ํ•˜)
CREATE INDEX idx_orders_unprocessed_bad ON orders (created_at);

-- [TO-BE] ๋ฏธ์ฒ˜๋ฆฌ ์ฃผ๋ฌธ 5๋งŒ ๊ฑด๋งŒ ์™ ๊ณจ๋ผ ์ธ๋ฑ์‹ฑ (์šฉ๋Ÿ‰ 95% ์ ˆ๊ฐ, ์••๋„์  ์†๋„)
CREATE INDEX idx_orders_unprocessed_good 
ON orders (created_at) 
WHERE status IN ('PENDING', 'PROCESSING');

โ‘ก ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค (Covering Index with INCLUDE) โ€“ Table Random Access ์ œ๊ฑฐ

์ธ๋ฑ์Šค๋ฅผ ํ†ตํ•ด ํ–‰์˜ ์œ„์น˜๋ฅผ ์ฐพ์€ ๋’ค ์‹ค์ œ ์ปฌ๋Ÿผ ๊ฐ’์„ ์ฝ์œผ๋Ÿฌ ํ…Œ์ด๋ธ” ํž™(Heap) ์˜์—ญ์œผ๋กœ ๊ฑด๋„ˆ๊ฐ€๋Š” Table Access ๊ณผ์ •์„ ์—†์• ์ฃผ๋Š” ๊ธฐ์ˆ ์ž…๋‹ˆ๋‹ค. PostgreSQL 11๋ถ€ํ„ฐ ์ง€์›๋˜๋Š” INCLUDE ์ ˆ์„ ์“ฐ๋ฉด B-Tree ํŠธ๋ฆฌ ํƒ์ƒ‰ ํ‚ค๊ฐ€ ์•„๋‹Œ ํŽ˜์ด๋กœ๋“œ ๋ฐ์ดํ„ฐ๋กœ๋งŒ ์ปฌ๋Ÿผ์„ ํฌํ•จ์‹œ์ผœ ์ธ๋ฑ์Šค ํฌ๊ธฐ๋ฅผ ์Šฌ๋ฆผํ•˜๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

-- user_id๋กœ ํƒ์ƒ‰ํ•˜๊ณ  total_price๋ฅผ ์ธ๋ฑ์Šค ํŽ˜์ด๋กœ๋“œ์— ํฌํ•จ
CREATE INDEX idx_orders_user_covering 
ON orders (user_id) 
INCLUDE (total_price, order_date);

-- ์‹คํ–‰๊ณ„ํš์—์„œ 'Index Only Scan'์ด ๋œจ๋ฉฐ ํ…Œ์ด๋ธ” I/O๊ฐ€ 0์œผ๋กœ ์ˆ˜๋ ด!
SELECT user_id, total_price, order_date 
FROM orders 
WHERE user_id = 95210;

โ‘ข BRIN (Block Range Index) โ€“ ๋Œ€์šฉ๋Ÿ‰ ์‹œ๊ณ„์—ด/๋กœ๊ทธ ๋ฐ์ดํ„ฐ์˜ ๊ตฌ์›ํˆฌ์ˆ˜

IoT ์„ผ์„œ ๋ฐ์ดํ„ฐ๋‚˜ ๋กœ๊ทธ ํ…Œ์ด๋ธ”์ฒ˜๋Ÿผ ์ˆ˜์–ต ๊ฑด์ด ๋งค์ผ ์‹œ๊ฐ„ ์ˆœ์„œ๋Œ€๋กœ ์Œ“์ด๋Š” ํ…Œ์ด๋ธ”์— ์ผ๋ฐ˜ B-Tree ์ธ๋ฑ์Šค๋ฅผ ๊ฑธ๋ฉด ์ธ๋ฑ์Šค ํฌ๊ธฐ๋งŒ ์ˆ˜์‹ญ GB์— ๋‹ฌํ•ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ง‘์–ด์‚ผํ‚ต๋‹ˆ๋‹ค. ์ด๋•Œ BRIN์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌผ๋ฆฌ์  ๋ธ”๋ก ๋ฒ”์œ„์˜ ์ตœ์†Œ/์ตœ๋Œ€๊ฐ’๋งŒ ์ €์žฅํ•˜๋ฏ€๋กœ B-Tree ๋Œ€๋น„ 1/100 ๋ฏธ๋งŒ์˜ ์šฉ๋Ÿ‰์œผ๋กœ ์ดˆ๊ณ ์† ํƒ์ƒ‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ธ๋ฑ์Šค ์ข…๋ฅ˜ ์ ํ•ฉํ•œ ์‚ฌ์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค ์ €์žฅ ๊ณต๊ฐ„ / ์“ฐ๊ธฐ ์˜ค๋ฒ„ํ—ค๋“œ ํ•ต์‹ฌ ์žฅ์ 
B-Tree ๋ฒ”์šฉ์ ์ธ ๊ณ ์œ ํ‚ค, ์ •๋ ฌ, ๋ฒ”์œ„ ๊ฒ€์ƒ‰ ๋ณดํ†ต / ๋ณดํ†ต ๊ฐ€์žฅ ์•ˆ์ •์ ์ด๊ณ  ๋ฒ”์šฉ์ 
Partial Index ํŠน์ • ์กฐ๊ฑด(์˜ˆ: ํ™œ์„ฑ ์‚ฌ์šฉ์ž, ๋ฏธ์ฒ˜๋ฆฌ ์ฃผ๋ฌธ) ๋งค์šฐ ์ ์Œ / ๋งค์šฐ ๋‚ฎ์Œ ๋ถˆํ•„์š”ํ•œ ์“ฐ๊ธฐ ๋ถ€ํ•˜ ๋ฐ ์šฉ๋Ÿ‰ 90% ์ ˆ๊ฐ
Covering (INCLUDE) ํŠน์ • SELECT ์ปฌ๋Ÿผ ์กฐํšŒ๊ฐ€ ๋นˆ๋ฒˆํ•œ ํŒจํ„ด ๋ณดํ†ต / ์•ฝ๊ฐ„ ์ฆ๊ฐ€ Index Only Scan์œผ๋กœ ๋””์Šคํฌ I/O ์ œ๊ฑฐ
BRIN ์ˆ˜์–ต ๊ฑด์˜ ์‹œ๊ณ„์—ด ๋กœ๊ทธ, Append-Only ํ…Œ์ด๋ธ” ๊ทน์†Œ (์ˆ˜ MB ์ˆ˜์ค€) / ๊ทน์†Œ ์ดˆ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์˜ ์••๋„์  ๊ฐ€์„ฑ๋น„ ์ตœ์ ํ™”
GIN JSONB ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰, ์ „๋ฌธ ๊ฒ€์ƒ‰(Full-Text), ๋ฐฐ์—ด ํผ / ํผ ๋น„์ •ํ˜• ๋ฌธ์„œ ๋ฐ ๋‹ค์ค‘ ์š”์†Œ ๊ฒ€์ƒ‰ ์ตœ๊ฐ•์ž

3. ์‹ค๋ฌด์—์„œ ๋ฐฅ๋จน๋“ฏ ์ €์ง€๋ฅด๋Š” ์ธ๋ฑ์Šค ํŠœ๋‹ ์ตœ์•…์˜ ํ•จ์ • 3๊ฐ€์ง€

์•„๋ฌด๋ฆฌ ์ข‹์€ ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋†”๋„ ์ฟผ๋ฆฌ ์ž‘์„ฑ ์Šต๊ด€์ด ์—‰๋ง์ด๋ฉด ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” ๊ฐ€์ฐจ ์—†์ด Seq Scan(Full Table Scan)์„ ๋•Œ๋ ค๋ฒ„๋ฆฝ๋‹ˆ๋‹ค. ์ฃผ๋‹ˆ์–ด๋“ค์ด ๊ฐ€์žฅ ๋งŽ์ด ์‹ค์ˆ˜ํ•˜๋Š” ํŒจํ„ด์„ ์งš์–ด๋“œ๋ฆฝ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž ํ™”๋ฉด๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ถ„์„ ๋กœ๊ทธ
โ–ฒ ์ธ๋ฑ์Šค ์ปฌ๋Ÿผ ๊ฐ€๊ณต์€ ์˜ตํ‹ฐ๋งˆ์ด์ €๋ฅผ ๋ฌด๋ ฅํ™”์‹œํ‚ค๋Š” ์ฃผ๋ฒ”์ž…๋‹ˆ๋‹ค.

ํ•จ์ • 1: ์ธ๋ฑ์Šค ์ปฌ๋Ÿผ์„ ํ•จ์ˆ˜๋‚˜ ์—ฐ์‚ฐ์œผ๋กœ ๊ฐ์‹ธ๊ธฐ (SARGable ์œ„๋ฐ˜)

-- [BAD] created_at ์ปฌ๋Ÿผ์„ ํ•จ์ˆ˜๋กœ ๊ฐ์‹ธ๋ฉด ์ธ๋ฑ์Šค๋ฅผ ํƒ€์ง€ ๋ชปํ•˜๊ณ  ์ „์ฒด ํ…Œ์ด๋ธ” ์Šค์บ”!
SELECT * FROM orders WHERE DATE(created_at) = '2026-08-19';

-- [GOOD] ์ธ๋ฑ์Šค ์ปฌ๋Ÿผ์€ ์ˆœ์ˆ˜ํ•˜๊ฒŒ ๋‘๊ณ  ๋ฒ”์œ„๋ฅผ ์ง€์ •ํ•ด์•ผ Index Scan ์ž‘๋™
SELECT * FROM orders 
WHERE created_at >= '2026-08-19 00:00:00' 
  AND created_at < '2026-08-20 00:00:00';

ํ•จ์ • 2: ์•”๋ฌต์  ํ˜•๋ณ€ํ™˜(Implicit Type Cast)์˜ ํ•จ์ •

์ปฌ๋Ÿผ ํƒ€์ž…์€ VARCHAR์ธ๋ฐ WHERE ์กฐ๊ฑด์ ˆ์— ์ˆซ์ž ๋ฆฌํ„ฐ๋Ÿด WHERE phone_number = 01012345678 ํ˜•ํƒœ๋กœ ๋„˜๊ธฐ๋ฉด, DB๋Š” ๋ชจ๋“  ํ–‰์˜ ๋ฌธ์ž์—ด์„ ์ˆซ์ž๋กœ ๋ณ€ํ™˜ํ•˜๋А๋ผ ์ธ๋ฑ์Šค๋ฅผ ํฌ๊ธฐํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋“œ์‹œ ํƒ€์ž…์„ ์ผ์น˜์‹œํ‚ค์„ธ์š”!

ํ•จ์ • 3: ํ†ต๊ณ„ ์ •๋ณด์˜ ๋…ธํ›„ํ™” (Stats Out of Date)

ํ…Œ์ด๋ธ”์— ๋Œ€๊ทœ๋ชจ INSERT/DELETE๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”๋ฐ ํ†ต๊ณ„ ์ •๋ณด๊ฐ€ ๊ฐฑ์‹ ๋˜์ง€ ์•Š์œผ๋ฉด, ์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ ๋ฉ์ฒญํ•œ ํŒ๋‹จ์„ ๋‚ด๋ ค ์ข‹์€ ์ธ๋ฑ์Šค๋ฅผ ๋‘๊ณ ๋„ Seq Scan์„ ๋•๋‹ˆ๋‹ค. ์ •๊ธฐ์ ์ธ ANALYZE์™€ ์ ์ ˆํ•œ Autovacuum ํŠœ๋‹์€ ์„ ํƒ์ด ์•„๋‹Œ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

์‹œ๋‹ˆ์–ด์˜ ์ฟผ๋ฆฌ ํŠœ๋‹ ์‹ค์ „ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • 1. EXPLAIN (ANALYZE, BUFFERS)๋กœ Actual Time๊ณผ Shared Read ๋ฒ„ํผ๋ฅผ ํ™•์ธํ–ˆ๋Š”๊ฐ€?
  • 2. ๋ณตํ•ฉ ์ธ๋ฑ์Šค ์ƒ์„ฑ ์‹œ ์นด๋””๋„๋ฆฌํ‹ฐ(์„ ํƒ๋„)๊ฐ€ ๋†’์€ ์ปฌ๋Ÿผ์„ ์•ž์— ๋ฐฐ์น˜ํ–ˆ๋Š”๊ฐ€?
  • 3. ํŠน์ • ์ƒํƒœ๊ฐ’ ์กฐํšŒ์šฉ์ด๋ผ๋ฉด Partial Index๋กœ ํฌ๊ธฐ๋ฅผ ๋‹ค์ด์–ดํŠธํ–ˆ๋Š”๊ฐ€?
  • 4. WHERE ์ ˆ ์ขŒ๋ณ€์— ํ•จ์ˆ˜ ๋ž˜ํ•‘์ด๋‚˜ ์•”๋ฌต์  ํ˜•๋ณ€ํ™˜์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๊ฐ€?
  • 5. ๋ฏธ์‚ฌ์šฉ ์ธ๋ฑ์Šค๊ฐ€ ์Œ“์—ฌ INSERT/UPDATE ๋ณ‘๋ชฉ์„ ์œ ๋ฐœํ•˜๊ณ  ์žˆ์ง€ ์•Š์€๊ฐ€?

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŠœ๋‹์€ ๋งˆ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค. ์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์•„๊ฐ€๋Š” ๊ธธ์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ , ๊ทธ ๊ธธ๋ชฉ์— ์•Œ๋งž์€ ํ‘œ์ง€ํŒ(์ธ๋ฑ์Šค)์„ ๊ฝ‚์•„์ฃผ๋Š” ์—”์ง€๋‹ˆ์–ด๋ง ์ž‘์—…์ด์ฃ . ์˜ค๋Š˜ ๋ฐฐ์šด EXPLAIN ๋ฒ„ํผ ๋ถ„์„๊ณผ ์ƒํ™ฉ๋ณ„ ํŠน์ˆ˜ ์ธ๋ฑ์Šค๋ฅผ ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ์— ์ง์ ‘ ์ ์šฉํ•ด ๋ณด์„ธ์š”. ์Šฌ๋กœ์šฐ ์ฟผ๋ฆฌ ๋กœ๊ทธ๊ฐ€ ๊ธฐ์ ์ฒ˜๋Ÿผ ์‚ฌ๋ผ์ง€๋Š” ์งœ๋ฆฟํ•จ์„ ๋ง›๋ณด์‹œ๊ฒŒ ๋  ๊ฒ๋‹ˆ๋‹ค! ๐Ÿš€

ps. ์‚ฌ์‹ค ์š”์ฆ˜์—” AIํ•œํ…Œ ์ฟผ๋ฆฌ์™€ ์‹คํ–‰๊ณ„ํš์„ ๋™์‹œ์— ๋ณด์—ฌ์ฃผ๋ฉด ์•Œ์•„์„œ ์ž˜ ํŠœ๋‹ ํ•ด์ค๋‹ˆ๋‹ค. ใ…‹ใ…‹

์ด ๊ธ€์ด ๋งˆ์Œ์— ๋“œ์…จ๋‚˜์š”? ๋ฐ˜์‘์„ ๋‚จ๊ฒจ์ฃผ์„ธ์š”!
๐Ÿ’ก ๋ณธ ๊ฒŒ์‹œ๋ฌผ์˜ ๋ชจ๋“  ์ €์ž‘๊ถŒ์€ ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ์ž์—๊ฒŒ ์žˆ์œผ๋ฉฐ ๋ฌด๋‹จ ์ „์žฌ ๋ฐ ์žฌ๋ฐฐํฌ๋ฅผ ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋Œ“๊ธ€ 0

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค. ์ฒซ ๋Œ“๊ธ€์„ ๋‚จ๊ฒจ๋ณด์„ธ์š”!

๋ณธ ์‚ฌ์ดํŠธ๋Š” ์›ํ™œํ•œ ์„œ๋น„์Šค ์ œ๊ณต์„ ์œ„ํ•ด ์ฟ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํžˆ ์•Œ์•„๋ณด๊ธฐ