PostgreSQL을 다루다 보면 반드시 마주치는 키워드가 바로 VACUUM입니다. 많은 RDBMS 사용자, 특히 MySQL에 익숙한 개발자라면 처음 접했을 때 낯설 수 있습니다. 이번 글에서는 VACUUM의 개념과 동작 방식, PostgreSQL 17에서의 개선점, 그리고 MySQL과의 차이를 정리해보겠습니다.


1. VACUUM이란 무엇인가?

PostgreSQL은 MVCC 구조로 인해 테이블 안에 [죽은 튜플(dead tuple)]이 쌓입니다. DELETE나 UPDATE가 발생하면 행을 바로 제거하지 않고, 새로운 버전을 만들어 기존 버전은 더 이상 보이지 않게 처리할 뿐입니다. 하지만 물리적으로는 남아있기 때문에, 이를 정리해주는 과정이 필요합니다.

➡️ 이 과정을 수행하는 명령이 바로 VACUUM입니다.


2. VACUUM의 주요 역할

  1. 죽은 튜플 공간 회수: 더 이상 참조되지 않는 데이터를 치워 디스크 공간 확보.
  2. 통계 업데이트: 옵티마이저가 최신 실행 계획을 세울 수 있도록 통계 정보를 갱신.
  3. 트랜잭션 ID Wraparound 방지: PostgreSQL은 트랜잭션 ID가 40억 정도에서 다시 0으로 돌아오는데, VACUUM이 이를 예방해 데이터 일관성을 유지.

3. Autovacuum

  • VACUUM을 수동으로 계속 실행하기는 어렵기 때문에, PostgreSQL은 Autovacuum 데몬을 기본으로 제공합니다.
  • 특정 테이블에 죽은 튜플이 일정 비율 이상 쌓이면 자동으로 VACUUM을 실행합니다.
  • 주요 파라미터:
    • autovacuum_vacuum_scale_factor: 테이블 크기에 비례한 트리거 비율.
    • autovacuum_analyze_scale_factor: ANALYZE 자동 실행 비율.
    • autovacuum_naptime: 주기적 확인 주기.

🔧 운영에서는 대용량 테이블마다 Autovacuum 튜닝이 필수입니다.


4. PostgreSQL 17에서의 개선점

  • VACUUM 메모리 관리 최적화: 대규모 테이블 VACUUM 시 메모리 사용량이 줄어 안정성이 향상되었습니다.
  • 대량 적재/삭제 환경에서 Autovacuum 동작 효율이 올라가 관리 부담이 줄었습니다.

➡️ 대규모 PaaS 환경에서는 특히 체감 차이가 큽니다.


5. MySQL에서는 왜 VACUUM이 없는가?

  • MySQL(InnoDB)은 삭제/갱신 시 Undo Log에만 기록하고, 테이블에는 최신 버전만 유지합니다.
  • 불필요해진 Undo Log는 Purge Thread가 비동기적으로 정리합니다.
  • 공간 단편화가 심한 경우에는 OPTIMIZE TABLE 명령으로 테이블을 재구성합니다.

➡️ 즉, VACUUM은 PostgreSQL 특유의 개념이며, MySQL에서는 Purge Thread + OPTIMIZE TABLE로 대체된다고 보면 됩니다.


6. 실무에서의 주의사항

  • 긴 트랜잭션: 오랫동안 열린 트랜잭션은 Autovacuum이 죽은 튜플을 정리하지 못하게 막습니다. → 디스크 폭증 위험.
  • Autovacuum 튜닝: 테이블마다 업무 패턴에 맞는 스케일 팩터 조정 필요.
  • 수동 VACUUM: 배치 작업 직후, 대량 삭제 후에는 VACUUM FULL로 디스크 공간 회수.

7. 정리

  • VACUUM은 PostgreSQL 운영에서 가장 중요한 관리 개념 중 하나.
  • MySQL에는 직접 대응되는 개념이 없고, Undo Log/Purge Thread로 처리.
  • PostgreSQL 17에서는 VACUUM 성능이 개선되어 대규모 운영 환경에서 안정성이 강화.

다음 편 예고

3편에서는 PostgreSQL의 jsonb와 인덱싱 기법을 살펴보겠습니다. 이 기능은 반정형 데이터를 다루는 현대 애플리케이션에서 PostgreSQL이 MySQL보다 선호되는 가장 큰 이유 중 하나입니다.


 

+ Recent posts