1.Vacuum 이란?
사전적 의미로 진공, 빨아들이다로 청소기라는 의미로 사용됩니다.
PostgresSQL 에서는 오래된 영역을 정리하여 공간을 반환하는 명령어 입니다.
즉 Vacuum은 윈도우의 디스크 조각모음과 유사한 기능으로 볼 수 있습니다.
[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)
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).
예시)
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이 걸리기 때문)
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 의 프로세스 개수를 정의
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
Dead Tuple 수가 설정된 값보다 높다면, Auto Vacuum이 동작합니다.
Dead Tuple > Autovacuum_vacuum_threshold (50) + Autovacuum_vacuum_scale_fator (0.2) * reltuples(n_live_tup)
테이블 AGE가 autovacuum_freeze_max_age 설정으로 지정한 트랜잭션 수보다 많다면, vacuum 작업 수행(default : 2억)
예시)
현재autovacuum_freeze_max_age는 100,000 으로 최소값이 설정되어 있으며,
순차적으로 DB에 vacuum이 수행 설정 값보다 낮은 값으로 age가 설정
(※ 데이터베이스의 age는 해당 DB에서 값이 제일 높은 테이블의 age가 표시)
[autovacuum_freeze_max_age = 100000 설정 후 autovacuum on 설정]
[Autovacuum 프로세스 동작 확인]
참고사이트
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