본문 바로가기
Database2024년 6월 3일5분 읽기

PostgreSQL VACUUM 이해 — 데드 튜플과 성능 유지

YS
김영삼
조회 218

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

아직 댓글이 없습니다.
Ctrl+Enter로 등록