PostgreSQL 주기적인 유지관리 Vacuuming



주기적인 유지관리 Vacuuming

Vacuum 기초

 - PostgreSQL의 Vacuum 명령은 다음과 같은 이유로 각 테이블마다 정기적으로 프로세스 해야합니다.

 a. 업데이트 또는 삭제된 행이 점유한 디스크 공간의 복구 또는 재사용.
 b. PostgreSQL 쿼리 플래너가 사용하는 데이터 통계 업데이트 (DB통계정보)
 c. 인덱스 전용 스캔 속도를 높이는 가시도 맵(visibility map) 업데이트
 d. 트랜잭션 ID 랩어라운드 또는 multixact ID 랩어라운드에 의한 아주 오래된 데이터가 손실되지 않도록 보호
 
 Vacuum에는 두가지 변이인 표준 Vacuum과 Vacuum Full이 있습니다. Vacuum Full은 디스크 공간을 더 많이 회수하는 대신 실행이 느립니다. 또한, 표준형 Vacuum은 데이터베이스 작업과 병렬로 실행할 수 있습니다. (Vacuum 진행중에 DDL (alter) 명령은 안되나 DML (select,insert,delete,update) 명령은 정상 작동함)
 Vacuum Full 작업은 작업중인 테이블에 대해 배타적 잠금이 필수이므로, 테이블의 다른 작업과 병렬로 사용할 수 없습니다.
 Vacuum은 상당한 I/O 트래픽이 발생되며, 다른 활성 세션의 성능을 저하시키는 원인이 됩니다.
 
1) 디스크 공간 복구

 - PostgreSQL에서 행의 UPDATE 또는 DELETE는 행의 오래된 버전을 즉각 제거하지 않습니다. 이러한 접근법은 MVCC의 장점을 누리기 위한것으로, 다른 트랜잭션에서 계속 확인될 가능성이 있을 경우에는 행 버전을 삭제해서는 안됩니다. 그러나 오래되었거나 삭제된 행 버전은 트랜잭션 대상이 아니기 때문에 Vacuum으로 회수 가능합니다.
 - 표준형 Vacuum은 테이블과 인덱스에서 Deed row 버전을 삭제하고, 나중에 재사용할 수 있도록 가용 공간으로 표시합니다. 하지만 테이블에 쓸수 있는 공간이 있는 경우는 오래된 공간을 반환하지 않습니다.
 - Vacuum Full은 Dead space가 일절 없도록 모든 공간을 반환합며, 테이블을 새버전으로 작성함으로 테이블이 최소화되지만, 시간이 오래걸리는 단점이 있습니다.
 - 일상적인 Vacuuming의 목표는 Vacuum Full이 불필요 하도록 표준형 Vacuum을 충분히 실행하는 것입니다. autovacuum데몬은 이와 같은 방식을 작동 되며, 사실상 Vacuum Full을 절대 수행하지 않습니다.
 
2) 실행 계획 통계 업데이트

 - PostgreSQL 쿼리 플래너는 쿼리에 대해 괜찮은 플랜을 생성하기 위해, 테이블 내용에 대한 통계정보에 의존합니다. 이러한 통계는 자체적으로 호출하거나 Vacuum에서 옵션으로 처리하거나 ANALYZE 명령으로 생성됩니다.
 - autovacuum 데몬이 활성화 되면 테이블 내용이 바뀔때마다 ANALYZE 명령이 자동으로 실행됩니다. 업데이트가 빈번하더라도, 데이터의 통계적 분포가 많이 바뀌지 않을때는 통계를 업데이트를 할 필요가 없습니다.

3) visibility map 업데이트

 - Vacuum은 모든 활성 트랜잭션에 보이는 것으로 알려진 튜플만 포함된 페이지를 추적하기 위하여 각 테이블에 대한 visibility map을 관리합니다.
 - 첫번째 목적은 Vacuum 자체는 cleanup 할 것이 없으므로 다음 실행에서 해당 페이지를 스킵합니다.
 - 두번째 목적은 기저 테이블을 참조하지 않고 인덱스만 이용하여 PostgreSQL이 일부 쿼리에 응답할 수 있게 합니다. 테이블을 참조 하지 않고 인덱스만 스캔하는 경우 visibility map을 먼저 확인하기 때문에 페이지에 튜플이 보이는 경우 heep fetch를 스킵할 수 있습니다. 거대 데이터 세트에서는 visibility map이 디스크 액세스를 막을 수 있는 가장 확실한 방법입니다. visibility map은 heep 보다 훨씬 작기때문에 heep이 매우 클 경우에도 쉽게 캐쉬 됩니다.

4) 트랜잭션 ID 랩어라운드 실패 방지

 - PostgreSQL의 MVCC 트랜잭션 시멘틱은 트랜잭션 ID(XID) 번호의 비교 가능 여부에 달려있습니다. 트랜잭션 ID의 크기는 제한되어 있으므로(32비트) 장시간 (40억 트랜잭션 이상) 동안 실행되는 클러스터는 트랜잭션 ID 랩어라운드가 발생합니다. XID 카운트가 0으로 랩어라운드 되고 과거에 있었던 모든 트랜잭션이 미래에 나타나게 됩니다. 즉 데이터의 소실이 발생합니다. 이 것을 피하려면 피하려면 20억 트랜잭션마다 모든 데이터베이스의 모든 케이블을 Vacuum해야 합니다.
 - 주기적으로 Vacuuming으로 문제가 해결되는 이유는 이 행이 과거에 커밋된 트랜잭션에 의해 삽입되었고 삽입 트랜잭션의 결과로 MVCC 관점으로 부터 현재와 미래 트랜잭션에서 모두 보이는 것이 확실하도록 Vacuum이 행에 동결 표시를 한다는 것입니다.
 
5) Multixact 및 랩어라운드

 - Multixact ID는 복수 트랜잭션에 의한 행 잠금을 지원할 때 사용됩니다.
 - Vacuum 테이블 스캔 중에, 테이블 부분적으로 또는 전체적으로 vacuum_multixact_freeze_min_age보다 오래된 multixact ID는 서로 다른 값으로 교체되는데, 이 값은 0, 단일 트랜잭션ID 또는 신규 multixact ID일 수 있습니다. 테이블 별로 pg_class.relminmxid는 해당 테이블에 계속 나타날 가능성이 있고 가장 오래된 multixact ID를 저장합니다. 이 값이 vacuum_multixact_freeze_min_age보다 오래된 경우 전체 테이블 스캔이 강제됩니다.
 - 전체 테이블 Vacuum 스캔은 사용된 멤버 저장소 공간이 할당된 저장소 공간의 50%를 초과 할 경우 multixact 연령이 가장 오래된 것을 시작으로 모든 테이블에 대해 순처적으로 일어납니다.
 
6) Autovacuum 데몬
 
 - Autovacuum 데몬의 목적은 Vacuum과 ANALYZE 명령의 실행을 자동화하는 것입니다.
 - autovacuum이 활성화 되면 다수의 튜플이 삽입, 업데이트 또는 삭제된 테이블을 검사합니다. 이 검사는 통계 수집 기능을 사용합니다. 따라서 track_counts가 true로 설정되지 않으면 사용할 수 없습니다.