query plan부터 시작해, 가장 비싼 부분을 고치세요. EXPLAIN/EXPLAIN ANALYZE로 데이터베이스가 실제로 무엇을 하는지 보고, 올바른 를 추가하고, query를 제거하고, 필요한 데이터만 select하세요.
EXPLAIN ANALYZE는 실행 계획과 실제 시간을 보여줍니다. 큰 테이블에 대한 Seq Scan은 전형적인 경고 신호입니다:
EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 42;
-- Seq Scan on orders (cost=0.00..18500 rows=120)
-- Filter: (customer_id = 42)
-- rows removed by filter: 999880 ← 테이블 전체를 스캔!
index는 full scan을 빠른 lookup으로 바꿉니다:
CREATE INDEX idx_orders_customer ON orders (customer_id);
-- 이제: Index Scan using idx_orders_customer (cost=0.42..8.5 rows=120)
-- 1,000,000행 스캔 → ~120행 lookup
index는 쓰기에 비용이 있습니다: 모든 INSERT/UPDATE가 index도 갱신해야 하므로, filter/join/sort하는 컬럼에 index를 — 모든 컬럼이 아니라. composite index (customer_id, created_at)는 WHERE customer_id = ? ORDER BY created_at를 하나의 구조로 처리합니다.
N+1 문제 — 목록을 위한 query 하나, 그 다음 각 행마다 하나 — 는 느림의 주요 원인입니다. eager loading, JOIN, 또는 배치 IN (...)으로 대체하세요:
-- N+1: 1 + 100 query
SELECT * FROM orders; -- 그다음 order마다: SELECT * FROM users WHERE id = ?
-- 수정: 하나의 JOIN, 필요한 컬럼만
SELECT o.id, o.total, u.name
FROM orders o JOIN users u ON u.id = o.user_id;
또한 필요한 컬럼만 select하고(SELECT * 피하기) LIMIT/keyset pagination으로 페이지네이션하여 수백만 행을 절대 로드하지 마세요.
데이터베이스는 가장 흔한 병목입니다. plan을 읽으면 추측 대신 query가 왜 느린지 알 수 있고; 올바른 index, N+1 제거, 결과 집합 축소는 하드웨어 확장 없이도 초 단위 query를 밀리초 단위로 흔히 바꿉니다.
주니어부터 시니어까지 상세한 답변이 포함된 IT 면접 질문 라이브러리.
후원하기