DB 엔지니어링 — 파티셔닝 (Range·List·Hash)

2026-05-03확률과 통계 마스터 노트

데이터베이스 엔지니어링 마스터 노트 시리즈 3편. 수평 vs 수직 파티셔닝의 결정적 차이, Range·List·Hash 3가지 파티션 전략, Partition Pruning이 인덱스 없이도 빠른 이유, 파티셔닝의 장점(작은 인덱스·병렬 처리)과 단점(JOIN 복잡·UNIQUE 제약), 파티셔닝 vs 샤딩까지 — 4편 샤딩의 토대를.

이 글은 데이터베이스 엔지니어링 마스터 노트 시리즈의 세 번째 편입니다. 2편(인덱싱)이 단일 테이블의 빠른 조회였다면, 이번엔 테이블 자체를 쪼개는 파티셔닝.

수십억 행 테이블에서 인덱스만으로는 한계. 파티셔닝으로 물리적 단위 자체를 나누면 성능·관리 비용·백업 시간 모두 개선.

파티셔닝이란?

큰 테이블을 작은 조각(파티션)으로 분할. 논리적으로 한 테이블처럼 보이지만 물리적으로는 여러 파일.

products (논리 테이블)
  ├── products_2024_q1 (1~3월)
  ├── products_2024_q2 (4~6월)
  ├── products_2024_q3 (7~9월)
  └── products_2024_q4 (10~12월)

쿼리는 단일 테이블처럼 작성, DBMS가 자동으로 적절한 파티션만 조회.

수평 vs 수직 파티셔닝

종류 설명
수평 (Horizontal) 행 단위 분할 (날짜·범위·해시)
수직 (Vertical) 컬럼 단위 분할 (자주/안 자주 쓰는 컬럼)

수평 파티셔닝 — 표준

users 테이블 (1억 행)
  ↓ user_id 범위로 분할
  ├── users_p1: id 1~1000만
  ├── users_p2: id 1000만~2000만
  └── ...

대부분 "파티셔닝" = 수평 파티셔닝.

수직 파티셔닝

products 테이블
  ├── products_main: id, name, price, stock (자주 조회)
  └── products_meta: id, description, reviews (가끔 조회)

이미지·블롭처럼 큰 컬럼을 분리. 사실상 수직 파티셔닝은 테이블 정규화와 비슷.

여기서 시험 함정이 하나 있어요. 수평 파티셔닝과 수직 파티셔닝은 다른 도구. 일반적으로 파티셔닝 = 수평. 수직은 정규화로 해결.

Range Partitioning — 범위

-- PostgreSQL
CREATE TABLE orders (
    id BIGINT,
    order_date DATE,
    amount DECIMAL
) PARTITION BY RANGE (order_date);

CREATE TABLE orders_2024_q1 PARTITION OF orders
    FOR VALUES FROM ('2024-01-01') TO ('2024-04-01');

CREATE TABLE orders_2024_q2 PARTITION OF orders
    FOR VALUES FROM ('2024-04-01') TO ('2024-07-01');

용도 — 시간 기반 데이터 (로그·주문·거래).

장점 — 오래된 파티션 통째 DROP으로 빠른 삭제. 인덱스 재구성 X.

-- 2024년 Q1 데이터 통째 삭제 (1초)
DROP TABLE orders_2024_q1;

-- vs DELETE는 매우 느림
-- DELETE FROM orders WHERE order_date < '2024-04-01';

List Partitioning — 명시적 값

CREATE TABLE customers (
    id BIGINT,
    country VARCHAR(2)
) PARTITION BY LIST (country);

CREATE TABLE customers_kr PARTITION OF customers
    FOR VALUES IN ('KR');

CREATE TABLE customers_us PARTITION OF customers
    FOR VALUES IN ('US', 'CA');

CREATE TABLE customers_eu PARTITION OF customers
    FOR VALUES IN ('DE', 'FR', 'UK');

용도 — 카테고리 기반 (국가·지역·상태).

Hash Partitioning — 균등 분산

CREATE TABLE users (
    id BIGINT,
    email VARCHAR
) PARTITION BY HASH (id);

CREATE TABLE users_p0 PARTITION OF users
    FOR VALUES WITH (MODULUS 4, REMAINDER 0);

CREATE TABLE users_p1 PARTITION OF users
    FOR VALUES WITH (MODULUS 4, REMAINDER 1);

-- ... p2, p3

용도 — 균등 분산이 핵심일 때. 특정 범위·국가에 편중 없음.

여기서 정말 중요한 시험 함정 — Hash 파티션은 범위 쿼리 X. WHERE id BETWEEN 1000 AND 2000 → 모든 파티션 스캔. Range·List와 결정적 차이.

Partition Pruning — 핵심 최적화

쿼리에 파티션 키가 있으면 DBMS가 해당 파티션만 조회.

-- 파티션 키(order_date) 사용 → Pruning 작동
EXPLAIN SELECT * FROM orders WHERE order_date = '2024-05-15';
-- → orders_2024_q2만 스캔 (다른 파티션 X)

-- 파티션 키 없음 → Pruning 작동 X
EXPLAIN SELECT * FROM orders WHERE customer_id = 100;
-- → 모든 파티션 스캔 (느림)

여기서 정말 중요한 시험 함정 — Pruning은 파티션 키가 WHERE에 있을 때만. 자주 조회하는 컬럼을 파티션 키로 선정하는 게 핵심.

파티셔닝 장점

  1. 작은 인덱스 — 파티션마다 인덱스 → 트리 깊이 ↓ → 캐시 적중 ↑
  2. 빠른 삭제DROP PARTITION 즉시
  3. 병렬 처리 — 여러 파티션 동시 스캔
  4. 백업/복구 단위 — 파티션별
  5. 다른 스토리지 — 핫 파티션 SSD, 콜드 파티션 HDD

파티셔닝 단점

1. UNIQUE 제약 한계

-- 파티션 키가 포함된 UNIQUE만 가능
CREATE UNIQUE INDEX ON orders (order_date, id);  -- ◯

-- 단일 컬럼 글로벌 UNIQUE X
-- CREATE UNIQUE INDEX ON orders (id);  -- 에러 (모든 파티션에 동일 ID 가능)

여기서 시험 함정이 하나 있어요. PostgreSQL 파티션 테이블은 글로벌 UNIQUE 제약 X (파티션 키 포함해야). MySQL도 비슷한 제약.

2. 외래 키 제약

대부분 DBMS에서 파티션 테이블 → 외래 키 참조 또는 받기 제한.

3. 쿼리 복잡

파티션 키 안 쓰는 쿼리는 모든 파티션 스캔 → 단일 테이블보다 느릴 수도.

4. 파티션 키 변경 (UPDATE)

-- order_date를 다른 파티션으로 이동시키는 UPDATE
UPDATE orders SET order_date = '2024-08-15' WHERE id = 100;
-- 파티션 간 이동 → 비싸거나 불가

여기서 시험 함정이 하나 있어요. 파티션 키 UPDATE는 비용 큼. PostgreSQL은 일정 조건에서 자동 이동, 일부 DBMS는 거부. 파티션 키는 변경 안 되는 컬럼으로.

파티셔닝 vs 샤딩

구분 Partitioning Sharding
범위 단일 DB 안 여러 DB·서버
투명성 DBMS가 처리 애플리케이션 처리
관리 단일 DB 관리 분산 시스템 관리
적합 단일 노드 한계 안 단일 노드 초과

여기서 정말 중요한 시험 함정 — Partitioning은 DB 안에서 분할, Sharding은 여러 서버에 분할. 파티셔닝 한계 도달 = 샤딩 (4편).

PostgreSQL 파티셔닝 데모

-- 1. 파티션 테이블 생성
CREATE TABLE logs (
    id BIGSERIAL,
    log_time TIMESTAMP NOT NULL,
    message TEXT
) PARTITION BY RANGE (log_time);

-- 2. 파티션 생성
CREATE TABLE logs_2024_01 PARTITION OF logs
    FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');

CREATE TABLE logs_2024_02 PARTITION OF logs
    FOR VALUES FROM ('2024-02-01') TO ('2024-03-01');

-- 3. 데이터 삽입 (자동으로 파티션 라우팅)
INSERT INTO logs (log_time, message) VALUES
    ('2024-01-15', 'Hello'),
    ('2024-02-20', 'World');

-- 4. 쿼리 (Pruning 자동)
SELECT * FROM logs WHERE log_time = '2024-01-15';
-- → logs_2024_01만 스캔

동적 파티션 관리

운영 환경 — 자동 파티션 생성 도구 사용.

-- pg_partman 확장 (PostgreSQL)
SELECT partman.create_parent(
    'public.logs',
    'log_time',
    'native',
    'monthly'
);
-- 매월 자동으로 새 파티션 생성

또는 cron으로 매월 실행.

파티션 키 선정

좋은 파티션 키:

  • WHERE 절에 자주 등장
  • 범위 또는 카테고리 분명
  • 변경 안 됨
  • 균등 분산

피해야 할 키:

  • 자주 UPDATE
  • 한 값에 데이터 편중 (skew)
  • WHERE에 안 쓰임

시험 직전 한 번 더 — 자주 헷갈리는 함정 모음

여기까지가 3편의 핵심입니다. 시험 직전 또는 실무에서 헷갈릴 때 다시 펼쳐 볼 수 있게 압축 노트로 마무리할게요.

  • 파티셔닝 = 큰 테이블을 작은 조각으로 분할
  • 논리 한 테이블 / 물리 여러 파일
  • 수평 (행 단위) vs 수직 (컬럼 단위)
  • 일반적으로 파티셔닝 = 수평
  • 수직은 정규화와 비슷
  • 3 전략 — Range / List / Hash
  • Range = 시간·범위 (시간 데이터 표준)
  • List = 명시적 카테고리 (국가·상태)
  • Hash = 균등 분산
  • Hash는 범위 쿼리 X — 모든 파티션 스캔
  • Partition Pruning = 파티션 키 WHERE 시 해당 파티션만
  • 파티션 키 없는 쿼리 = 모든 파티션
  • 장점 — 작은 인덱스·빠른 삭제·병렬·백업·티어드 스토리지
  • 단점 — UNIQUE 제약 한계·외래 키·복잡 쿼리·파티션 키 UPDATE 비용
  • PostgreSQL 글로벌 UNIQUE X (파티션 키 포함해야)
  • 파티션 키 UPDATE = 파티션 간 이동, 비용 큼
  • 파티션 키는 변경 안 되는 컬럼
  • Partitioning ≠ Sharding
  • Partitioning = 단일 DB 안 / Sharding = 여러 서버
  • DROP PARTITION = 빠른 삭제 (DELETE보다 1000배+)
  • pg_partman 등으로 자동 파티션 생성
  • 좋은 파티션 키 — WHERE 등장·범위·불변·균등

시리즈 다른 편

공식 문서: PostgreSQL Partitioning에서 더 깊이.

다음 글(4편)에서는 샤딩 — 파티셔닝의 단일 DB 한계를 넘어 여러 서버로, Consistent Hashing, 샤딩 키 선정의 핵심까지 풀어 갑니다.

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!