PostgreSQL의 VACUUM은 MVCC(다중 버전 동시성 제어, Multi-Version Concurrency Control)로 인해 발생하는 Dead Tuple(사용되지 않는 데이터)을 정리하는 과정.

  • VACUUM이 없으면 PostgreSQL 테이블 크기가 계속 증가하고 성능이 저하됨.
  • Dead Tuple이 많아지면 SELECT 속도가 느려지고, INSERT/UPDATE 시 불필요한 I/O가 증가.
  • VACUUM을 효율적으로 설정하면 PostgreSQL 성능을 최적화할 수 있음.

 

1️⃣ VACUUM이 필요한 이유

🔹 PostgreSQL은 DELETE와 UPDATE 시 데이터를 실제로 삭제하지 않는다!

PostgreSQL의 MVCC 특성상 DELETE 또는 UPDATE가 실행되면 기존 데이터를 변경하지 않고 새로운 버전을 생성한다.

  • DELETE: 데이터가 즉시 삭제되지 않고 삭제 표시(xmax 값이 설정됨)만 됨.
  • UPDATE: 기존 데이터가 Dead Tuple이 되고, 새로운 Tuple이 생성됨.
UPDATE user SET name = 'Alice Smith' WHERE id = 1;

 

실제 데이터 변경 과정

ctid id name xmin xmax
(0,1) 1 Alice 1001 1002
(0,2) 1 Alice Smith 1002 NULL

Dead Tuple이 많아지면 VACUUM이 필요함!

VACUUM이 없으면 테이블 크기가 계속 증가하며 성능 저하 발생

 

 

2️⃣ VACUUM의 종류

PostgreSQL에서는 여러 가지 VACUUM 방식이 있다.

 

VACUUM 종류 설명 Dead Tuple 제거 디스크 공간 회수 Exclusive Lock 필요
VACUUM 기본적인 Dead Tuple 정리
VACUUM ANALYZE VACUUM + 통계 정보 갱신
(Query Planner 최적화)
VACUUM FULL Dead Tuple 제거 + 디스크 공간 반환
AUTOVACUUM 자동으로 백그라운드에서 실행됨

일반적으로는 AUTOVACUUM을 사용하지만, 필요 시 VACUUM FULL을 실행해야 함.

 

 

3️⃣ VACUUM 동작 과정

(1) VACUUM 기본 동작 원리

  1. Dead Tuple 스캔: 테이블을 읽으며 Dead Tuple을 찾음.
  2. Dead Tuple을 Free Space Map(FSM)에 등록: 추후 INSERT가 같은 공간을 활용할 수 있도록 함.
  3. Index 유지보수: 인덱스에서 참조되지 않는 Tuple을 제거.
  4. Transaction ID Wraparound 방지: autovacuum_freeze_max_age를 초과한 경우 FREEZE 실행.

VACUUM을 실행하면 테이블 크기가 줄어드는 것이 아니라, Dead Tuple이 제거되고 기존 공간을 재사용 가능하게 됨.디스크 공간을 줄이려면 VACUUM FULL을 실행해야 함.

 

(2) VACUUM ANALYZE

  • VACUUM과 ANALYZE를 함께 실행하여 Dead Tuple 정리 후 통계 정보를 업데이트.
  • Query Planner가 최신 통계를 반영하여 최적의 실행 계획을 선택 가능.
  • SELECT 성능이 저하된 경우 VACUUM ANALYZE를 실행하면 해결될 가능성이 큼.

실행 방법

VACUUM ANALYZE user;
 

Query Planner가 통계를 활용하는지 확인

EXPLAIN ANALYZE SELECT * FROM user WHERE name = 'Alice';
  • Seq Scan(전체 테이블 스캔)이 발생하면 통계 정보가 최신이 아닐 수 있음.

 

(3) VACUUM FULL

  • VACUUM과 다르게 테이블 크기를 실제로 줄여줌.
  • Dead Tuple을 제거하고, 기존 테이블을 새로운 테이블로 재구성.
  • 하지만, Exclusive Lock이 필요하기 때문에 실행 중에는 테이블을 사용할 수 없음.

실행 방법

VACUUM FULL user;
 

VACUUM FULL 실행 시 고려해야 할 점

  • 테이블 크기가 줄어들지만, 잠금(Lock)이 발생하여 서비스에 영향을 줄 수 있음.
  • 일반적인 운영 환경에서는 피하는 것이 좋음 (가능하면 비활성 시간대에 실행).

 

4️⃣ Autovacuum (자동 VACUUM)

🔹 Autovacuum이란?

  • PostgreSQL은 Dead Tuple이 일정 수준을 초과하면 자동으로 VACUUM을 실행함.
  • 수동으로 VACUUM을 실행하지 않아도 PostgreSQL이 최적의 시점에서 자동으로 실행.

(필자 의견)

최적의 시점에 Vacuum 이 동작해도 리소스( CPU, 메모리 )를 사용한다.

테이블 사용이 peak 인 시간에 동작한다면, 리소스 고갈로 장애로 이어질 수 있다.

필자는 Autovacuum을 선호하지 않는다.

 

 

5️⃣ Dead Tuple 및 VACUUM 상태 확인

Dead Tuple 확인

autovacuum = on
autovacuum_vacuum_threshold = 500  # 기본값: 50 → 변경이 500건 이상이면 VACUUM 실행
autovacuum_vacuum_scale_factor = 0.05  # 기본값: 0.2 → 5% 변경 시 VACUUM 실행
autovacuum_naptime = 30s  # 기본값: 1min → 더 자주 실행
vacuum_cost_limit = 2000  # 기본값: 200 → VACUUM 성능 향상
  • dead_tuple_ratio > 20%이면 VACUUM 실행 필요!

최근 VACUUM 실행 여부 확인

SELECT relname, last_vacuum, last_autovacuum 
FROM pg_stat_user_tables
WHERE schemaname = 'public';

 

 

6️⃣ VACUUM 최적화 전략

Dead Tuple이 많다면 VACUUM ANALYZE 실행

VACUUM ANALYZE [테이블명];
 

테이블 크기를 줄이고 싶다면 VACUUM FULL 실행

VACUUM FULL [테이블명];
 

Autovacuum이 너무 자주 실행된다면 autovacuum_vacuum_threshold 값을 높이기

autovacuum_vacuum_threshold = 1000
 

HOT(Heap-Only Tuple) 최적화로 VACUUM 부담 줄이기

ALTER TABLE users SET (fillfactor = 80);
 

테이블 크기가 너무 커지면 CLUSTER 실행

CLUSTER user USING user_pkey;
※ 실행 중 테이블이 잠기므로 OLTP 환경에서는 신중하게 실행해야 함

 

 

✅ 결론

🔹 PostgreSQL의 VACUUM은 MVCC로 인해 생성된 Dead Tuple을 정리하는 과정
🔹 VACUUM을 실행하지 않으면 테이블 크기가 계속 증가하고 SELECT 성능이 저하됨
🔹 VACUUM ANALYZE를 실행하면 Dead Tuple을 정리하고 Query Planner 통계를 최신화 가능
🔹 VACUUM FULL은 디스크 공간을 회수하지만, Exclusive Lock이 필요하여 신중하게 실행해야 함
🔹 Autovacuum을 적절히 튜닝하면 자동으로 Dead Tuple을 관리 가능

 

 

'PostgreSQL' 카테고리의 다른 글

PostgreSQL - Tuple  (0) 2025.02.23
PostgreSQL - MVCC (Multi-Version Concurrency Control)  (0) 2025.02.23
PostgreSQL - Memory - Shared Buffer  (0) 2025.02.22
PostgreSQL - Memory - Backend Buffer  (0) 2025.02.22
PostgreSQL - Idle Session' Memory  (0) 2025.02.22

+ Recent posts