핵심 요약
파티셔닝은 거대 테이블을 쿼리 패턴에 맞는 작은 단위로 나눠 불필요한 스캔을 제거한다. 성능 이점의 대부분은 파티션 프루닝에서 나온다.
언제 파티셔닝을 해야 하나
- 단일 테이블이 수천만 행 이상
- 쿼리가 특정 범위·키에 집중
- 오래된 데이터 대량 삭제가 필요 (DROP PARTITION이 DELETE보다 수천 배 빠름)
- 인덱스 유지비용이 너무 큰 경우
파티셔닝 종류
RANGE (시계열 기본 선택)
CREATE TABLE events (
id BIGSERIAL,
created_at TIMESTAMPTZ NOT NULL,
payload JSONB
) PARTITION BY RANGE (created_at);
CREATE TABLE events_2026_04 PARTITION OF events
FOR VALUES FROM ('2026-04-01') TO ('2026-05-01');
LIST (카테고리)
CREATE TABLE orders (region TEXT, ...) PARTITION BY LIST (region);
CREATE TABLE orders_kr PARTITION OF orders FOR VALUES IN ('KR');
CREATE TABLE orders_us PARTITION OF orders FOR VALUES IN ('US');
HASH (균등 분산)
CREATE TABLE sessions (user_id BIGINT, ...) PARTITION BY HASH (user_id);
CREATE TABLE sessions_0 PARTITION OF sessions FOR VALUES WITH (MODULUS 8, REMAINDER 0);
파티션 프루닝 확인
EXPLAIN (ANALYZE, BUFFERS)
SELECT count(*) FROM events
WHERE created_at >= '2026-04-10' AND created_at < '2026-04-11';
계획에 Partitions removed by partitioning: N이 보이면 정상.
자동 파티션 관리
pg_partman을 쓰면 월/일 단위 파티션이 자동 생성·폐기된다.
CREATE EXTENSION pg_partman;
SELECT partman.create_parent(
'public.events', 'created_at', 'range', 'monthly',
p_premake := 6
);
인덱스 전략
- 부모 테이블에 선언하면 모든 파티션에 자동 전파
- UNIQUE/PK는 파티션 키 포함 필수
- 핫 파티션만 BRIN 대신 B-Tree 고려 (쿼리 패턴별)
데이터 이관 시나리오
- 새 파티션 테이블 생성 (구 테이블과 동일 스키마)
- INSERT INTO new_partition SELECT ... FROM old_table WHERE ...
- 앱 쓰기를 트리거/듀얼 라이트로 전환
- 이관 완료 후
ATTACH PARTITION으로 통합 - 구 테이블 rename → drop
실무 함정
- 기본 파티션(
DEFAULT) 없이 삽입 시 실패 → 항상 생성 - COPY는 파티션별로 라우팅되지만 대량 COPY는 lock 경합
- 파티션 1000개 이상은 플래너 비용 급증 → 계층 파티셔닝 고려
자주 묻는 질문
샤딩과 파티셔닝 차이?
파티셔닝은 단일 DB 내 논리 분할. 샤딩은 여러 DB/노드 분산. 먼저 파티셔닝으로 해결되면 그 선에서 끝내는 것이 운영 비용상 유리.
파티션 수 상한?
수백 개까지 무난, 천 단위부터 플래너 overhead 체감. 큰 경우 LIST-of-RANGE 계층 파티셔닝.
댓글 0