PostgreSQL Vacuum 소개

2022-01-26

 


1.Vacuum 이란?

사전적 의미로 진공, 빨아들이다로 청소기라는 의미로 사용됩니다.
PostgresSQL 에서는 오래된 영역을 정리하여 공간을 반환하는 명령어 입니다.
즉 Vacuum은 윈도우의 디스크 조각모음과 유사한 기능으로 볼 수 있습니다.

Postgres_01.jpg
[Vacuum = 디스크 조각 모음]

PostgreSQL에서는 옛 데이터의 변경(Update/Insert/Delete)이 발생해도 해당 내역들을 즉시 제거하지 않고 지속적으로 보관합니다.
이를 MGA(Multi Generation Architecture) 구조라고 부르며, 오래된 영역들을 회수하여 재사용하기 위해 Vacuum 명령어를 사용하여 정리합니다.
* Vacuum의 실행 구조
  1. 기존 테이블에 Update 발생 (BBB? bbb)
  2. 기존 데이터 BBB 와 bbb가 지속적으로 보관
  3. DDD라는 새로운 데이터 insert 시, FSM 확인 후 빈 공간에 데이터 추가
  4. Vacuum이 발생하면서 불필요한 정보가 삭제 (옛 데이터 BBB vacuum)

Untitled-1_02.png


2.Vacuum의 역할

 데이터 재사용을 위한 방법 외에도 다음과 같은 역할을 위해 사용합니다.
 1) 변경 및 삭제된 튜플(dead tuple) 들이 차지하고 있는 디스크 공간을 확보 - vacuum, vacuum full
 2-1) Query Planner가 사용할 자료의 통계정보 갱신 - vacuum analyze
 2-2) 인덱스 전용 검색 성능을 향상시키는 실 자료 지도 정보를 갱신
 3) 트랜잭션 ID (=TXID = age) 가 겹침으로 인해 오래된 자료의 손실이 발생하는 것을 방지 - vacuum freeze
(언급된 모든 Vacuum의 역할을 자동으로 수행할 수 있는 Auto Vacuum 기능은 PG 8.1ver에 추가되었습니다.)
 
조금 더 상세한 내용을 살펴보겠습니다. 



1) 디스크 여유 공간 확보 (Vacuum , Vacuum Full)
  - Update, Delete 작업 후 옛 데이터를 바로 삭제하지 않아 디스크에는 쓸모 없는 데이터가 생기게 됩니다. 즉 Vacuum 작업으로 옛 데이터를 정리 후 빈 공간으로 만들어 디스크에 대한 공간 확보합니다.
  이러한 역할은 Vacuum 과 Vacuum Full 이 담당하며, 사용하는 목적과 차이가 있습니다.
·Vacuum
   - 테이블, 인덱스에서 삭제된 자료(dead row)를 정리, 그 자리에 다른 자료가 저장 될 수 있도록 빈 공간으로 표시
  > 주기적인 작업으로 빈 공간을 확보 Vacuum Full 작업 상황을 방지 역할
  > 디스크의 최소 여유 공간 확보가 아닌 최적의 디스크 사용을 의미
  > AutoVacuum 데몬의 수행 방법임
 
·Vacuum Full
  - 사용할 수 있는 데이터를 따로 모아 새 파일에 저장하며, 최적의 물리적 크기의 공간을 생성합니다. (윈도우 디스크 조각모음과 동일).
 > 디스크 공간을 최소로 사용하여 쓸모없는 공간을 운영체제 쪽으로 반환
 > 대용량 테이블을 관리하는 입장에서는 비효율적
 > Table에 Exclusive Lock을 발생시키기 때문에 운영 중 사용 불가

2-1) Query Planner가 사용할 자료의 통계정보 갱신 (Vacuum Analyze)
 - PostgreSQL 쿼리 실행 계획기는 각 테이블의 데이터로 만든 통계정보를 이용하여 쿼리의 실행계획을 만들게 됩니다. 이러한 통계 정보의 갱신 작업이 제대로 되지 않는다면, 의도 되지않은 실행계획이 짜여지고, 데이터베이스의 성능을 떨어뜨리는 결과를 초래하게 됩니다.
   이 때 Vacuum Analyze 명령을 이용하여 주기적으로 바른 통계 정보 갱신 작업을 수행해야 합니다.
 
2-2) 실 자료 지도 갱신
  - 트랜잭션이 사용할 데이터에 대한 테이블 지도를 갱신
  - 테이블 페이지까지 직접 검색하지 않고 실 자료 지도를 검색해 효율적인 쿼리 실행을 수행.
    (테이블 크기가 큰 경우에 디스크 읽기 작업을 상당히 줄이는 효과를 볼 수 있음)
 결과적으로 autovacuum 데몬이 주기적으로 Vacuum Analyze를 수행하여 통계정보를 생성하게 됩니다. (다만, 세세한 경우까지 고려하지 않으며, 테이블의 데이터 추가,변경,삭제 된 경우에만 작업 고려 대상으로 판단합니다.)

3) 트랜잭션 ID 관리
  - PostgreSQL에서는 처리되거나 처리될 각각의 모든 트랜잭션에 대해 트랜잭션ID를 부여합니다.(MVCC 구조) 하나의 tuple을 처리할 때 두 개의 트랜잭션 ID(XID)를 갖게 되며, older와 newer로 각각 20억 개씩(최대 40억) 할당 받게 됩니다. (40억개 = older 20억, newer 20억)
object 생성 시 트랜잭션ID(age)는 1로 생성되며, 데이터베이스에 트랜잭션이 하나씩 발생할 때마다 모든 object의 나이는 1씩 증가합니다.
- MVCC 방식 (다중 버전 동시성 제어) 란?
데이터 변수행이 완료될 때까지 변경사항은 다른 데이터베이스 사용자가 볼 수 없도록 차단하기위하여, 트랜잭션 XID 값을 비교하여 보여질 데이터와 보이지 말아야 할 데이터로 나뉘게 됩니다.(older = visible , newer = invisible)
 현재 트랜잭션 XID 값  < Older XID (= insert)
 현재 트랜잭션 XID 값  > Newer XID (=update, Delete).
  
Postgres_03.jpg


예시)  
Insert(older XID) ? xmin
Update, Delete(Newer XID) ? max
xmin ~ xmax 사이의 트랜잭션들은 다음과 같이 구분됨
-       트랜잭션 1815 는 AAA, BBB, CCC 을 볼 수 있다.
-       트랜잭션 1821 는 BBB, CCC, XXX 을 볼 수 있다.
-       트랜잭션 1831 는 BBB, XXX 을 볼 수 있다.

  - 만약 한정된 트랜잭션 수(40억)을 넘어 1부터 다시 시작하게 된다면, 모든 데이터의 XID 값은 1보다 크기 때문에 볼 수 없는 자료로 처리되어 큰 문제가 발생합니다.
  이런 상황을 해결하고자 Postgres는 오래된 데이터에 대한 손실발생 방지(XID wraparound) 를 위해 튜플에 FREEZE로 표시하며, FrozenXID 비교 대상에서 제외시키며 영구 보관용 자료로 항상 보여지게 됩니다.
  이러한 변경 작업(data freezing)은 Vacuum Freeze명령으로 처리하며, Auto Vacuum의 역할입니다.


3.     Vacuum의 종류

1)     Vacuum Command
VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ]
VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]
 
    [ FULL ]                        많은 공간을 확보하기 위해 사용하지만, 오래 걸리며 이전 테이블 정보를 사용해 Lock이 발생합니다.
    [ FREEZE ]                     튜플의 TXID 고정하여 vacuum을 수행합니다.
    [ VERBOSE ]                  각 테이블에 대한 상세한 vacuum 동작의 보고를 해줍니다.
    [ ANALYZE ]                  쿼리 통계를 업데이트 합니다.
    [ DISABLE_PAGE_SKIPPING ]   FSM 을 기준으로 페이지를 건너뛰며, FSM문제가 의심되는 경우에만 사용합니다.
    [ SKIP_LOCKED ]             vacuum 작업이Lock 해체가 될때까지 기다리지 않도록 지정하거나 건너뜁니다.
    [ INDEX_CLEANUP ]         인덱스 청소를 건너뛸때 사용합니다(기본값은 AUTO)
    [ PROCESS_TOAST ]         TOAST 테이블을 처리하도록 지정할때 사용합니다.
    [ PARALLEL ]                   integer 백그라운드 작업자를 사용하여 인덱스 vacuum 및 인덱스 정리 단계를 병렬로 수행합니다.
and table_and_columns is:
    table_name [ ( column_name [, ...] ) ]
 

Vacuumdb Command
- Vaccum 실행하는 클라이언트 명령어
 
사용법 :  vacuumdb [옵션]... [DB이름] 
옵션들 :
  -a, --all                          모든 데이터베이스 청소
  -d, --dbname=DBNAME    DBNAME 데이터베이스 청소
  -e, --echo                      서버로 보내는 명령들을 보여줌
  -f, --full                         대청소 (Table Lock 발생)
  -F, --freeze                     행 트랜잭션 정보 동결
  -q, --quiet                     어떠한 메시지도 보여주지 않음
  -t, --table='TABLE[(COLUMNS)]'  지정한 특정 테이블만 청소
  -v, --verbose                  작업내역의 자세한 출력
  -V, --version                   output version information, then exit
  -z, --analyze                   update optimizer statistics
  -Z, --analyze-only            only update optimizer statistics
  -?, --help                       show this help, then exit
연결 옵션들 :
  -h, --host=HOSTNAME     데이터베이스 서버 호스트 또는 소켓 디렉터리
  -p, --port=PORT              데이터베이스 서버 포트
  -U, --username=USERNAME   접속할 사용자이름
  -w, --no-password           암호 프롬프트 표시 안 함
  -W, --password               암호 프롬프트 표시함
  --maintenance-db=DBNAME   alternate maintenance database    [ PARALLEL ]
and table_and_columns is:
    table_name [ ( column_name [, ...] ) ]
 
2)     Auto Vacuum
Auto Vacuum 은 Vacuum, Analyze, Freeze 명령을 (autovacuum_naptime : 1분) 자동 실행.
주기적인 Vacuum 작업을 하여 빈 공간을 확보, 최대한 Vacuum Full 작업을 방지함(Table의 Lock이 걸리기 때문)

Postgres_05.jpg

Auto Vacuum의 역할

 - DBA가 예상하지 못한 상황에 대한 주기적인 vacuum 작업
 - 추가/변경/삭제 된 테이블들을 체크 vacuum 실행 (Dead tuple 삭제)
 - 통계정보 갱신(vacuum analysize)
 - 트랜잭션 ID 겹침 방지 작업  (XID Wrap Around)
  >> Auto Vacuum의 데몬이 작업을 멈추거나, 비정상적으로 작동 ? 데이터베이스의 Age(TXID) 증가, 디스크 사용 용량의 문제가 발생!!!
    데이터베이스의 기동에 문제가 생길 수 있으며, 수동으로 상황에 맞는 Vacuum 작업을 해주어야 합니다.

Auto Vacuum 설정

- Autovacuum_freeze_max_age
  한 테이블 내에서 마지막 vacuum 작업으로 pg_class,relfozenxid 값이 지정된 뒤로 이 설정 값 보다 더 커지면 vacuum 작업 수행
- Autovacuum_vacuum_threshold / autovacuum_analyze_threshold (기본값 50)
  한 테이블 내에서 업데이트/삭제된 튜플(dead tuple)의 수를 설정하여, vacuum/analyze 작업 진행
- Autovacuum_vacuum_scale_factor (기본값 0.2)
  한 테이블 내의 threshold 값으로 vacuum 작업을 진행하려 할 때, 테이블 크기의 변화량을 확인하여 작업 진행 (기본값은 0.2 = 테이블 크기의 20%)
- Autovacuum_vacuum_cost_limit
  Autovacuum 데몬이 사용할 수 있는 최대 비용을 설정
- Autovacuum_vacuum_cost_delay
  Autovacuum 데몬의 초과 비용 사용시, 멈추는 최대 시간
- Autovacuum_work_mem
  Autovacuum이 동작할 때의 메모리를 설정 (서버 메모리 1GB 당 50MB 할당)
- Autovacuum_max_workers
  Autovacuum 의 프로세스 개수를 정의

Postgres_06.jpg

Auto Vacuum 이 작업하는 기준
Dead Tuple 수가 설정된 값보다 높다면, Auto Vacuum이 동작합니다.
Dead Tuple > Autovacuum_vacuum_threshold + Autovacuum_vacuum_scale_fator * reltuples.

Vacuum 임계치 = Vacuum 초기 임계치 + Vacuum 배율값 * 튜플 수(로우 수)
 * Vacuum 초기 임계치 : autovacuum_vacuum_threshold
 * Vacuum 배율값 : autovacuum_vacuum_scale_factor
 * 튜플수 : pg_class,reltuples
Postgres_07.jpg

Dead Tuple 수가 설정된 값보다 높다면, Auto Vacuum이 동작합니다.
Dead Tuple > Autovacuum_vacuum_threshold (50) + Autovacuum_vacuum_scale_fator (0.2) * reltuples(n_live_tup)

Untitled-1_08.png

테이블 AGE가 autovacuum_freeze_max_age 설정으로 지정한 트랜잭션 수보다 많다면, vacuum 작업 수행(default : 2억)

예시)
현재autovacuum_freeze_max_age는 100,000 으로 최소값이 설정되어 있으며,
순차적으로 DB에 vacuum이 수행 설정 값보다 낮은 값으로 age가 설정
(※ 데이터베이스의 age는 해당 DB에서 값이 제일 높은 테이블의 age가 표시)

Postgres_09.jpg



[autovacuum_freeze_max_age = 100000 설정 후 autovacuum on 설정]
Postgres_08_10.jpg

[Autovacuum 프로세스 동작 확인]
Postgres_08_11.jpg


참고사이트
https://www.postgresql.org/docs/current/routine-vacuuming.html
https://distributedsystemsauthority.com/configuring-vacuum-for-performance-postgresql-12-high-performance-guide-part-4-12/
https://bstar36.tistory.com/tag/PostgreSQL%20vacuum
https://blog.gaerae.com/2015/09/postgresql-vacuum-fsm.html

PostgreSQL Vacuum 소개
전용재
기술본부 DB기술2팀 선임

이전 글

답답한 성능과 헤어질 결심

다음 글

셀파 V5 주요 개선 사항

목록보기