MVCC와 데드 튜플
PostgreSQL은 MVCC(Multi-Version Concurrency Control)를 사용하여 동시성을 처리합니다. UPDATE나 DELETE 시 기존 행을 즉시 삭제하지 않고, 새 버전을 추가한 뒤 이전 버전을 '사망(dead)' 상태로 표시합니다. 이 사망한 행이 데드 튜플(dead tuple)입니다.
데드 튜플이 쌓이면?
- 테이블 크기가 불필요하게 커짐 (Table Bloat)
- 인덱스 크기 증가 (Index Bloat)
- Sequential Scan 성능 저하
- 디스크 공간 낭비
- Transaction ID Wraparound 위험
VACUUM 동작 원리
VACUUM my_table;
VACUUM ANALYZE my_table;
-- VACUUM FULL은 운영 중 사용 금지 - 전체 테이블 잠금
VACUUM FULL my_table;
VACUUM VERBOSE my_table;
데드 튜플 모니터링
SELECT
schemaname, relname, n_live_tup, n_dead_tup,
ROUND(n_dead_tup::numeric / NULLIF(n_live_tup, 0) * 100, 2) AS dead_pct,
last_vacuum, last_autovacuum, last_analyze
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;
SELECT
tablename,
pg_size_pretty(pg_total_relation_size(tablename::regclass)) AS total_size,
pg_size_pretty(pg_relation_size(tablename::regclass)) AS table_size,
pg_size_pretty(pg_indexes_size(tablename::regclass)) AS index_size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(tablename::regclass) DESC;
Autovacuum 튜닝
전역 설정 (postgresql.conf)
autovacuum = on
autovacuum_max_workers = 5
autovacuum_naptime = 30s
autovacuum_vacuum_threshold = 50
autovacuum_vacuum_scale_factor = 0.1
autovacuum_vacuum_cost_delay = 2ms
autovacuum_vacuum_cost_limit = 800
테이블별 커스텀 설정
ALTER TABLE orders SET (
autovacuum_vacuum_scale_factor = 0.01,
autovacuum_vacuum_threshold = 100,
autovacuum_analyze_scale_factor = 0.005
);
ALTER TABLE access_logs SET (
autovacuum_vacuum_scale_factor = 0.5,
autovacuum_enabled = true
);
Transaction ID Wraparound 방지
SELECT
c.relname,
age(c.relfrozenxid) AS xid_age,
pg_size_pretty(pg_total_relation_size(c.oid)) AS size
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r' AND n.nspname = 'public'
ORDER BY age(c.relfrozenxid) DESC;
VACUUM 대신 pg_repack
sudo apt install postgresql-16-repack
pg_repack -t orders -d mydb
pg_repack --only-indexes -t orders -d mydb
실전 체크리스트
- pg_stat_user_tables의 n_dead_tup을 주기적으로 모니터링하세요.
- 대용량 테이블에는 테이블별 autovacuum 파라미터를 설정하세요.
- VACUUM FULL은 운영 환경에서 절대 함부로 실행하지 마세요. pg_repack을 사용하세요.
- Transaction ID Wraparound 경고를 모니터링 알림에 추가하세요.
댓글 0