데이터베이스 용어 사전
PostgreSQL선언적 파티셔닝 · PARTITION BY RANGE · 파티션 프루닝

파티셔닝

큰 테이블을 조각으로 나눠 저장하는 것. 조회 시 필요한 조각만 읽고, 오래된 조각은 통째로 버린다.

하나의 논리 테이블을 여러 물리 조각(파티션)으로 나눠 저장하는 것. 샤딩과 달리 한 서버 안에서 일어난다.

샤딩과 구분한다

파티셔닝한 DB 안에서 테이블을 쪼갠다→ 관리·조회 효율
샤딩여러 DB 서버로 데이터를 나눈다→ 쓰기·용량 확장

세 가지 방식

-- RANGE — 날짜·숫자 구간 (가장 흔하다)
CREATE TABLE orders (id BIGINT, created_at DATE, amount INT)
  PARTITION BY RANGE (created_at);
CREATE TABLE orders_2026_08 PARTITION OF orders
  FOR VALUES FROM ('2026-08-01') TO ('2026-09-01');

-- LIST — 값 목록
CREATE TABLE member PARTITION BY LIST (country);
CREATE TABLE member_kr PARTITION OF member FOR VALUES IN ('KR');

-- HASH — 고른 분산
CREATE TABLE log PARTITION BY HASH (user_id);
CREATE TABLE log_0 PARTITION OF log FOR VALUES WITH (MODULUS 4, REMAINDER 0);

이득 ① 파티션 프루닝 — 필요한 조각만 읽는다

EXPLAIN SELECT * FROM orders WHERE created_at >= '2026-08-01';
-- Append
--   ->  Seq Scan on orders_2026_08      ← 이 파티션만 읽는다
-- (다른 달 파티션은 계획에서 아예 빠진다)

조건에 파티션 키가 없으면 프루닝이 안 된다 — 모든 파티션을 읽게 되어 오히려 느려진다. 파티션 키 선택이 그래서 중요하다.

이득 ② 오래된 데이터를 통째로 버린다

-- DELETE 는 행마다 죽은 튜플을 만들고 VACUUM 부담을 남긴다
DELETE FROM orders WHERE created_at < '2025-01-01';   -- 느리고 bloat 를 만든다

-- 파티션이면 파일을 떼어내면 끝이다
ALTER TABLE orders DETACH PARTITION orders_2024_12;
DROP TABLE orders_2024_12;                            -- 즉시. bloat 없음

보존 기간이 있는 로그·이력 테이블에서 이것만으로도 파티셔닝을 할 이유가 된다.

주의할 점

  • PK·UNIQUE 제약에 파티션 키가 포함돼야 한다 (전역 유니크를 만들 수 없다)
  • 파티션이 너무 많으면 계획 수립 자체가 느려진다 (수백 개를 넘기지 않는다)
  • 파티션 생성을 자동화해야 한다 — 다음 달 파티션이 없으면 INSERT 가 실패한다
-- 기본 파티션을 두면 어디에도 안 맞는 행을 받아 준다 (INSERT 실패 방지)
CREATE TABLE orders_default PARTITION OF orders DEFAULT;

MySQL도 PARTITION BY RANGE를 지원하지만 PostgreSQL의 선언적 파티셔닝이 프루닝·관리 면에서 더 성숙하다.

면접 함정

  • "파티셔닝하면 무조건 빨라진다" → 파티션 키가 조건에 없으면 모든 파티션을 읽어 더 느려진다.
  • "파티셔닝은 샤딩이다" → 파티셔닝은 한 서버 안이고, 쓰기 확장 효과는 없다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — PostgreSQL 심화 — JSONB·파티셔닝·확장·VACUUM(17)