월별 range 파티션 테이블 생성(루프로 파티션 생성)
PostgreSQL파티셔닝명령어
CREATE TABLE sales (
id bigint GENERATED ALWAYS AS IDENTITY,
created_at date NOT NULL,
customer_id bigint NOT NULL,
amount numeric(12,2),
PRIMARY KEY (id, created_at)
) PARTITION BY RANGE (created_at);
-- An index defined on the parent propagates to all partitions automatically
CREATE INDEX sales_customer_id_idx ON sales (customer_id);
-- 12 monthly partitions for 2026
DO $$
DECLARE
m date;
BEGIN
FOR m IN SELECT generate_series(date '2026-01-01', date '2026-12-01', interval '1 month')::date LOOP
EXECUTE format(
'CREATE TABLE IF NOT EXISTS %I PARTITION OF sales FOR VALUES FROM (%L) TO (%L)',
'sales_' || to_char(m, 'YYYY_MM'), m, (m + interval '1 month')::date);
END LOOP;
END $$;
-- Hierarchy, bounds and sizes
SELECT t.relid::regclass AS partition_name,
t.parentrelid::regclass AS parent,
t.isleaf,
t.level,
pg_get_expr(c.relpartbound, c.oid) AS bounds,
pg_size_pretty(pg_total_relation_size(t.relid)) AS total_size
FROM pg_partition_tree('sales') t
JOIN pg_class c ON c.oid = t.relid
ORDER BY t.level, bounds;하는 일
날짜 컬럼에 RANGE 파티션 부모 테이블, 모든 파티션에 전파되는 인덱스, 루프로 월별 파티션 12개를 생성한다. 이후 계층 구조를 경계와 크기와 함께 나열한다.
사용 시점
오래된 데이터를 주기적으로 제거(DETACH/DROP)하거나 쿼리가 주로 날짜 범위로 필터링하는, 계속 커지는 대형 테이블(주문, 로그, 시계열)용.
주의
파티션 테이블에서 PRIMARY KEY/UNIQUE 제약 조건은 파티션 키를 포함해야 한다(전역 unique 인덱스가 없다). 하한은 포함, 상한은 제외다(FROM 포함, TO 제외). 미래 파티션을 미리 만드는 job(pg_cron, pg_partman)이 없으면 범위를 벗어난 INSERT가 실패한다. 파티션이 수천 개면 계획 시간과 락 오버헤드가 늘어난다. 부모에서는 CREATE INDEX CONCURRENTLY가 지원되지 않는다. 부모에 CREATE INDEX ... ON ONLY, 각 파티션에 CREATE INDEX CONCURRENTLY를 실행한 후 ALTER INDEX ... ATTACH PARTITION을 사용한다.