백엔드 데이터 인프라 22편. CREATE TABLE의 깊은 옵션 — PARTITION·INHERITS·UNLOGGED·TEMPORARY·CREATE TABLE AS 풀어쓴 학습 노트.
이 글은 백엔드 데이터 인프라 시리즈 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 없는 빠른 쓰기
CREATE UNLOGGED TABLE temp_cache (
id BIGSERIAL PRIMARY KEY,
payload JSONB
);
특징: - INSERT·UPDATE 매우 빠름 (WAL 안 쓰임) - 단점: 크래시 시 데이터 손실 — 자동 TRUNCATE - 복제 안 됨
용도: - 임시 캐시·세션 데이터 - 큰 ETL 임시 스테이징 - 정확성보다 속도 우선인 영역
운영 비즈니스 데이터 = 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 제외)
- 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
큰 텍스트의 디스크 압축 방식.
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 파티션 = 빠른 대량 삭제
- 파티션 인덱스 = 자동 적용
시리즈 다른 편
- Part 2 SQL Language 깊이: 19편 어휘 · 20편 SQL 문법 · 21편 DDL 개요 · 22편 (현재 글)
시리즈 다음 글
다음 글(23편)에서는 제약 깊이 — CHECK 표현식·DEFERRABLE·EXCLUDE·복합 제약.
공식 문서: PostgreSQL 18 — DDL: Basics에서 더 자세한 사양을 확인할 수 있어요.