반응형
설치·접속: PostgreSQL 설치와 접속
부제: 로그·이벤트처럼 계속 쌓이는 테이블을 월 단위로 나눠, 넣을 땐 자동으로 알맞은 조각에 들어가고 조회할 땐 필요한 조각만 스캔하고 싶을 때
-- 부모는 껍데기. 실제 데이터는 날짜 범위별 자식 테이블에 저장된다
CREATE TABLE m10_events (
id bigint GENERATED ALWAYS AS IDENTITY,
occurred_at date NOT NULL,
payload text
) PARTITION BY RANGE (occurred_at);
CREATE TABLE m10_events_2026_01 PARTITION OF m10_events
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
CREATE TABLE m10_events_2026_02 PARTITION OF m10_events
FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');
CREATE TABLE m10_events_2026_03 PARTITION OF m10_events
FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');
-- 부모에 넣으면 occurred_at을 보고 알맞은 자식으로 자동 라우팅
INSERT INTO m10_events (occurred_at, payload)
SELECT d, 'evt' FROM generate_series('2026-01-05'::date, '2026-03-25'::date, '5 days') d;
SELECT tableoid::regclass AS partition, count(*)
FROM m10_events GROUP BY 1 ORDER BY 1;
partition | count
--------------------+-------
m10_events_2026_01 | 6
m10_events_2026_02 | 5
m10_events_2026_03 | 5
(3 rows)파티셔닝은 하나의 논리 테이블을 여러 물리 테이블(파티션)로 쪼갠다. INSERT는 파티션 키(occurred_at)를 보고 자동으로 맞는 조각에 넣어 주므로, 애플리케이션 코드는 부모 테이블만 바라보면 된다. 진짜 이득은 조회할 때 나온다. WHERE occurred_at에 범위 조건을 걸면 옵티마이저가 관계없는 파티션을 아예 건너뛰는데(파티션 프루닝), 수억 행 테이블에서도 한 달치만 스캔한다. 오래된 데이터를 지울 때도 DELETE 대신 파티션을 통째로 DROP하면 순식간에 끝난다.
이렇게도 쓴다
특정 기간 조건을 걸면 그 파티션만 스캔한다(파티션 프루닝). (조합: EXPLAIN)
EXPLAIN (COSTS OFF)
SELECT count(*) FROM m10_events
WHERE occurred_at >= '2026-02-01' AND occurred_at < '2026-03-01';
-- -> Seq Scan on m10_events_2026_02 (2026-02 파티션 하나만 탄다)
범위가 아니라 값 목록으로 쪼갠다(지역·상태 코드 등). (조합: PARTITION BY LIST)
CREATE TABLE m10_by_region (id int, region text) PARTITION BY LIST (region);
CREATE TABLE m10_reg_kr PARTITION OF m10_by_region FOR VALUES IN ('KR','JP');
CREATE TABLE m10_reg_us PARTITION OF m10_by_region FOR VALUES IN ('US');
CREATE TABLE m10_reg_etc PARTITION OF m10_by_region DEFAULT; -- 나머지는 여기로
어느 파티션에도 안 맞는 값을 받아 주는 기본 파티션을 둔다. (조합: DEFAULT)
INSERT INTO m10_by_region VALUES (4,'FR'); -- KR/US 아닌 값 → m10_reg_etc
오래된 파티션을 통째로 버려 즉시 정리한다(DELETE보다 빠름). (조합: DROP/DETACH)
DROP TABLE m10_events_2026_01; -- 1월치 전부 제거
ALTER TABLE m10_events DETACH PARTITION m10_events_2026_02; -- 떼어내 보관
부모에 인덱스를 걸면 모든 파티션에 자동 전파된다.
CREATE INDEX ON m10_events (occurred_at); -- 자식마다 개별 인덱스 생성
기존 일반 테이블을 파티션으로 편입한다. (조합: ATTACH PARTITION)
ALTER TABLE m10_events ATTACH PARTITION m10_events_2026_04
FOR VALUES FROM ('2026-04-01') TO ('2026-05-01');반응형
'명령어 > DB' 카테고리의 다른 글
| [PostgreSQL] SERIALIZABLE 동시 갱신이 서로를 덮어써 lost update가 날 때 (0) | 2026.07.23 |
|---|---|
| [PostgreSQL] SELECT FOR UPDATE / NOWAIT / FOR SHARE 행을 잠그고 안전하게 갱신한다 (1) | 2026.07.23 |
| [PostgreSQL] 부분 인덱스(partial index)로 소수 행만 인덱싱한다 (0) | 2026.07.23 |
| [PostgreSQL] REFRESH MATERIALIZED VIEW CONCURRENTLY 갱신 중에도 조회를 막지 않는다 (0) | 2026.07.23 |
| [PostgreSQL] 머티리얼라이즈드 뷰 무거운 집계를 미리 구워 대시보드에서 즉답한다 (0) | 2026.07.23 |