백엔드 데이터 인프라 22편 — CREATE TABLE 깊이 PARTITION·UNLOGGED·TEMPORARY

2026-05-17백엔드 데이터 인프라

백엔드 데이터 인프라 22편. CREATE TABLE의 깊은 옵션 — PARTITION·INHERITS·UNLOGGED·TEMPORARY·CREATE TABLE AS 풀어쓴 학습 노트.

📚 백엔드 데이터 인프라 · 22편 — CREATE TABLE 깊이 PARTITION·UNLOGGED·TEMPORARY

이 글은 백엔드 데이터 인프라 시리즈 70편 중 22편이에요. 9편 CREATE TABLE 에서 "기본" 을 다뤘으니, 이번 22편은 운영에 필요한 깊은 옵션 — PARTITION·UNLOGGED·TEMPORARY·CREATE TABLE AS·LIKE·INHERITS.

PARTITION TABLE — 대용량의 핵심

대용량 데이터 (수천만~수십억 행) 의 운영 패턴. "한 큰 테이블 = 여러 파티션 조각".

RANGE 파티션 — 범위 기반

CREATE TABLE orders (
    id          BIGSERIAL,
    user_id     BIGINT NOT NULL,
    amount      INTEGER NOT NULL,
    created_at  TIMESTAMPTZ NOT NULL
) PARTITION BY RANGE (created_at);

-- 월별 파티션
CREATE TABLE orders_2026_05 PARTITION OF orders
    FOR VALUES FROM ('2026-05-01') TO ('2026-06-01');

CREATE TABLE orders_2026_06 PARTITION OF orders
    FOR VALUES FROM ('2026-06-01') TO ('2026-07-01');

장점은 세 가지로 요약돼요. 쿼리 시 "5월 데이터" 만 보면 5월 파티션만 스캔해서 수십 배 빠르고, 옛 데이터는 DROP TABLE orders_2024_01 한 줄로 지울 수 있어요 (DELETE 대신). 인덱스·VACUUM·통계도 모두 파티션별로 따로 돌아갑니다.

LIST 파티션 — 값 기반

CREATE TABLE customers (...)
PARTITION BY LIST (country);

CREATE TABLE customers_kr PARTITION OF customers FOR VALUES IN ('KR');
CREATE TABLE customers_jp PARTITION OF customers FOR VALUES IN ('JP');
CREATE TABLE customers_other PARTITION OF customers DEFAULT;

HASH 파티션 — 해시 기반

CREATE TABLE events (id BIGINT, ...)
PARTITION BY HASH (id);

CREATE TABLE events_p0 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE events_p1 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE events_p2 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE events_p3 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 3);

균등 분포 — 핫스팟 회피.

파티션 선택 룰

데이터 특성 파티션
시계열 (로그·주문·이벤트) RANGE (시간 기준)
카테고리·국가 LIST
균등 분포 필요 HASH

한국 회사 = RANGE 시간 파티션 거의 표준.

UNLOGGED TABLE — WAL 없는 빠른 쓰기

WAL (Write-Ahead Log, 변경 로그) 을 안 쓰는 테이블이에요.

CREATE UNLOGGED TABLE temp_cache (
    id BIGSERIAL PRIMARY KEY,
    payload JSONB
);

INSERT·UPDATE 가 매우 빠른 대신, 크래시가 나면 자동 TRUNCATE 돼서 데이터가 통째로 사라져요. 복제도 안 됩니다.

쓰는 자리는 임시 캐시·세션 데이터, 큰 ETL (Extract-Transform-Load, 데이터 이관 배치) 의 임시 스테이징, 정확성보다 속도가 우선인 영역 정도. 운영 비즈니스 데이터엔 ABSOLUTELY NO.

TEMPORARY TABLE — 세션 한정

CREATE TEMPORARY TABLE tmp_results (
    user_id BIGINT,
    score INTEGER
);

-- 또는 단축
CREATE TEMP TABLE tmp_results (...);

현재 세션에서만 보이고 (다른 세션 X), 세션이 끝나면 자동으로 사라져요. temp_buffers 메모리를 써서 빠르고, WAL도 안 씁니다.

복잡한 쿼리의 중간 결과를 잠깐 담아두거나, 한 트랜잭션·세션 안에서만 쓸 작업에 잘 맞아요.

CREATE TEMP TABLE tmp_high_value_users AS
SELECT user_id, SUM(amount) AS total
FROM orders
WHERE created_at > '2026-01-01'
GROUP BY user_id
HAVING SUM(amount) > 1000000;

SELECT u.*, tmp.total
FROM users u
JOIN tmp_high_value_users tmp ON u.id = tmp.user_id;

DROP TABLE tmp_high_value_users;

CREATE TABLE AS — 쿼리 결과로 테이블

CREATE TABLE active_users AS
SELECT id, name, email
FROM users
WHERE deleted_at IS NULL;

"한 번에 만들고 데이터 채우기". 백업·아카이브·실험에 자주.

-- 스키마만 (빈 테이블)
CREATE TABLE archive AS SELECT * FROM users WHERE 1=0;

WHERE 1=0 = 결과 0행 → 스키마만 복사.

CREATE TABLE LIKE — 구조 복사

CREATE TABLE archive (LIKE users INCLUDING ALL);

LIKE 옵션: - INCLUDING DEFAULTS — 기본값 복사 - INCLUDING CONSTRAINTS — 제약 (FK (Foreign Key, 외래 키) 제외) - INCLUDING INDEXES — 인덱스 - INCLUDING COMMENTS - INCLUDING ALL — 위 모두

-- 외래 키 제외 모든 것 복사
CREATE TABLE users_backup (LIKE users INCLUDING ALL EXCLUDING IDENTITY);

INHERITS — 옛 스타일 (권장 X)

18편 에서 짧게 본 상속.

CREATE TABLE animals (id BIGSERIAL PRIMARY KEY, name TEXT);
CREATE TABLE dogs (breed TEXT) INHERITS (animals);

PG 10+ 파티션이 INHERITS의 모던 대체. 새 코드 = 거의 안 씀.

컬럼 옵션 깊이

IDENTITY 옵션

id BIGINT GENERATED ALWAYS AS IDENTITY                  -- 강제 (사용자 INSERT 시 OVERRIDING 필요)
id BIGINT GENERATED BY DEFAULT AS IDENTITY              -- 기본값 (사용자가 박을 수 있음)
id BIGINT GENERATED ALWAYS AS IDENTITY (START 1000 INCREMENT 5)

생성 컬럼 (Generated Column)

CREATE TABLE products (
    id     BIGSERIAL,
    name   TEXT,
    price  INTEGER,
    tax    INTEGER,
    total  INTEGER GENERATED ALWAYS AS (price + tax) STORED
);

total = 항상 자동 계산. PG 12+ — 표준 SQL 호환.

STORED = 디스크에 저장 (PG는 STORED만 지원, VIRTUAL 18+ 일부 지원).

COLLATE — 정렬 순서

name TEXT COLLATE "ko_KR.utf8"

문자열 정렬·비교를 한국어 룰로.

COMPRESSION — PG 14+

description TEXT COMPRESSION lz4

큰 텍스트의 디스크 압축 방식 (lz4 (빠른 압축 알고리즘) · pglz (PG 기본 압축)).

STORAGE 옵션

CREATE TABLE logs (
    id BIGSERIAL,
    message TEXT
) WITH (fillfactor = 70, autovacuum_vacuum_scale_factor = 0.1);

fillfactor 는 페이지에 데이터를 채우는 비율 — HOT UPDATE (인덱스 갱신 없는 빠른 업데이트) 최적화에 쓰여요. autovacuum_* 은 테이블별로 vacuum 정책을 따로 거는 옵션.

대용량 운영에 매우 자주.

함정 5가지

(1) PARTITION KEY 누락

파티션 키가 PRIMARY KEY에 포함돼야 — 안 그러면 unique 보장 X.

CREATE TABLE orders (id BIGSERIAL, created_at TIMESTAMPTZ, ...)
PARTITION BY RANGE (created_at);

-- PK는 (id, created_at) 둘 다 포함해야
PRIMARY KEY (id, created_at)

(2) UNLOGGED 운영 데이터

크래시 = 데이터 전체 손실. 비즈니스 데이터엔 절대 X.

(3) INHERITS 신규 사용

파티션이 모던 표준. INHERITS는 옛 코드 호환용만.

(4) CREATE TABLE AS 시 제약 누락

CREATE TABLE archive AS SELECT * FROM users;
-- ❌ PRIMARY KEY·인덱스·제약 모두 사라짐

LIKE INCLUDING ALL + INSERT INTO ... SELECT 가 안전.

(5) Generated Column 변경

ALTER TABLE products ALTER COLUMN total ...
-- 생성 컬럼은 ALTER 제한 — DROP + 재생성
🎯 대용량 운영 표준

로그·주문·이벤트 = 월별 RANGE 파티션 무조건. 옛 파티션은 DROP TABLE 한 줄로 삭제. 인덱스·통계도 파티션별. 한국 회사 PG 운영 사실상 표준.

한 줄 정리 — PARTITION (RANGE·LIST·HASH) 으로 대용량 처리. UNLOGGED = 빠른 임시. TEMPORARY = 세션 한정. CREATE TABLE AS / LIKE 로 테이블 복사. Generated Column 으로 자동 계산. INHERITS는 옛 — 파티션이 대체.

시험 직전 한 번 더 — CREATE TABLE 깊이 입문자가 매번 헷갈리는 것

  • PARTITION TABLE = 대용량 운영 표준 (PG 10+)
  • RANGE = 시간·연속 값 (시계열)
  • LIST = 카테고리·국가
  • HASH = 균등 분포
  • 한국 표준 = 월별 RANGE
  • 파티션 키 = PRIMARY KEY 포함 필요
  • 옛 파티션 = DROP TABLE 한 줄
  • UNLOGGED = WAL 없음, 매우 빠름, 크래시 시 손실
  • 운영 데이터 = UNLOGGED 절대 X
  • TEMPORARY = 세션 한정
  • 자동 삭제 시점 = 세션 종료
  • CREATE TABLE AS = 쿼리 결과 → 테이블
  • WHERE 1=0 = 스키마만
  • CREATE TABLE LIKE = 구조 복사
  • INCLUDING DEFAULTS·CONSTRAINTS·INDEXES·ALL
  • INHERITS = 옛 (파티션 권장)
  • IDENTITY = SQL 표준 시퀀스
  • ALWAYS vs BY DEFAULT
  • Generated Column = 자동 계산 컬럼 (PG 12+)
  • STORED = 디스크 저장
  • COLLATE = 언어별 정렬
  • COMPRESSION = lz4·pglz (PG 14+)
  • WITH (fillfactor·autovacuum_*) = 테이블별 옵션
  • fillfactor 70 = HOT UPDATE 최적
  • DROP TABLE 파티션 = 빠른 대량 삭제
  • 파티션 인덱스 = 자동 적용

시리즈 다른 편 (앞뒤 글 모음)

이전 글:

다음 글:

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

답글 남기기

error: Content is protected !!