2. DBMS이야기/01. PostgreSQL

[PostgreSQL ADMIN] 정기적인 Vacuum 작업

OSSW(Open Source System SoftWare 2014. 11. 24. 14:08

1. 정기적인 Vacuum 작업

PostgreSQL 데이터베이스에서는 vacuum (배큠이라고 읽는다) 이라는 주기적인 관리 작업이 필요하다. (영어권에서는 vacuuming 단어는 '청소기 돌리기'라는 뜻으로 이미 일상 용어로 사용되고 있고, 이것을 데이터베이스 용어로 사용하였다. 이 글에서는 그냥 vacuum을 그대로 사용한다. - 옮긴이) 이 작업은 대부분의 서버 환경에서는 autovacuum 데몬이 담당해서 자동으로 처리 되기 때문에, 특별히 신경 쓸 필요는 없다.autovacuum 관련 환경 설정값을 바꾸어서 그 데몬의 동작 상태를 조절 할 수 있다. 또한 몇몇 데이터베이스 관리자는 VACUUM 명령을 직접 실행하는 것이 데이터베이스를 효율적으로 사용할 수 있다고 판단해서, cron 이나, 작업 스케줄러 같은 프로그램을 이용해서, 이런 주기적인 정리 작업을 한다. 이런 작업을 잘 하기 위해서는 여기서 설명하고 있는 내용을 잘 이해하고 있어야한다. autovacuum 기능을 이용하는 일반적인 환경에서 특별히 문제가 발생하지 않는다면, 게다가 다른 바쁜 일들이 많은 관리자라면 이 부분은 대충 읽어도 좋다.

1.1. Vacuum 기초

PostgreSQL에서 VACUUM 명령은 다음과 같은 여러 가지 이유로 정기적으로 각 테이블 단위로 실행되어야 한다:

 

 

  1. 변경 또는 삭제된 자료들이 차지 하고 있는 디스크 공간을 다시 사용하기 위한 디스크 공간 확보 작업이 필요하다.

  2. PostgreSQL 쿼리 실행 계획기가 사용할 자료 통계 정보를 갱신할 필요가 있다.

  3. 인덱스 전용 검색 성능을 향상하는데 이용하는 실자료 지도(visibility map, vm) 정보를 갱신하는 작업이 필요하다.

  4. 트랜잭션 ID 겹침이나, 다중 트랙잭션 ID 겹침 상황으로 오래된 자료가 손실 될 가능성을 방지해야할 필요가 있다.

이런 이유로 VACUUM 작업은 그 작업 이유에 맞게 다양한 주기로, 다양한 대상으로 진행된다. 이 부분에 대한 자세한 설명은 이 글의 하위 항목에서 각각 설명한다.

VACUUM 작업은 두 가지 종류가 있다: 표준 VACUUMVACUUM FULL이다. VACUUM FULL 작업은 물리적인 디스크 여유 공간을 확보할 수 있으나 그 작업 속도가 매우 느리다. 하지만 표준 VACUUM 작업은 운영 환경에서도 사용할 수 있도록 여러 다른 작업들(SELECT, INSERT, UPDATE, DELETE 이런 명령어로 수행되는 작업들)이 실행 되고 있어도 동시에 사용할 수 있다. (하지만, ALTER TABLE 명령과 같은 명령은 VACUUM 작업이 실행되고 있는 상황에서는 사용할 수 없다.) VACUUM FULL 명령은 해당 테이블에 대한 배타적 잠금(exclusive lock)을 지정하기 때문에, 어떤 작업도 할 수 없게 된다. 이렇기 때문에, 일반적 상황에서는 관리자는 VACUUM FULL 작업을 되도록이면 피하고, 표준 VACUUM 작업을 하겠끔 신경 써야한다.

VACUUM 작업은 추가적으로 디스크 입출력 부하를 만든다. 이 때문에 동시에 작업하고 있는 다른 세션의 성능을 떨어뜨린다. 

1.2. 디스크 여유 공간 확보

PostgreSQL에서는 UPDATEDELETE 작업 대상이 된 해당 자료의 옛 버전을 작업 완료 후 바로 버리지 않는다.  삭제된 자료를 다른 트랜잭션에서 사용하고 있다면, 그 자료가 삭제되면 안되기 때문이다. 하지만, 다른 트랜잭션이 더 이상이 그 옛 버전 자료에 대한 접근이 필요 없다면, 옛 버전 자료는 쓸모 없는 자료가 된다. 이 상태로 계속 운영 된다면, 디스크에는 쓸모 없는 자료들이 넘처나게 될 것이다. 이런 더 이상 사용할 수 없는, 사용해서는 안될 자료들을 정리해서 그 자료가 있었던 공간을 빈 공간으로 바꾸는 작업을 VACUUM 명령이 담당한다.

VACUUM 기본 작업은 테이블과 인덱스에서 삭제된 자료 (old version row, dead row 라고 한다) 를 정리하고, 그 자리를 다른 자료가 저장 될 수 있도록 빈공간으로 표시하는 것이다. 하지만, 이 작업은 운영체제 입장에서의 디스크 여유 공간을 확보하는 것을 의미하지는 않는다. 물론 한 테이블의 자료가 모두 지워졌고, 하나 또는 소수의 페이지만 없애면 되는데, 이 작업을 위해 테이블 전체의 배타적 잠금도 쉽게 할 수 있는 상황과 같이 특별한 경우는 해당 페이지를 삭제 해서 운영체제 입장의 디스크 여유 공간을 확보할 수도 있다. 이와 반대로, VACUUM FULL 작업은 해당 테이블의 사용할 수 있는 자료들만을 따로 모아 아에 새 파일에 저장하는 방식을 이용하기 때문에 운영체제 입장에서 디스크 여유 공간을 확보할 수 있다. 작업 결과로 해당 테이블에 대해서 최적의 물리적 크기로 테이블이 만들어진다. 하지만 그 작업은 일반 VACUUM 작업에 비해 시간이 꽤 걸린다. 또한 이 작업이 완료되기 전까지 이 작업을 할 수 있는 여유 공간이 있어야 작업을 할 수 있다.

일반적인 vacuum 전략은 주기적인 표준 VACUUM 작업을 해서, 꾸준히 빈 공간을 확보해서 디스크가 어느 정도 커지지만, 더 이상 크지지 않게 해서, 최대한 VACUUM FULL 작업을 해야하는 상황을 방지하는 것이다. autovacuum 데몬이 이런 전략으로 작업을 한다. 즉, autovacuum 기능을 사용한다면, VACUUM FULL 작업을 하지 않는 것을 기본 정책으로 하면 된다. 이런 전략은 각 테이블이 최소의 디스크 공간을 사용한다는 것을 의미하는 것이 아니라, 최적의 디스크 공간을 사용함을 의미한다. 각 테이블은 실재 자료가 저장되어 있는 공간과 함께 vacuum 작업으로 처리된 빈공간을 함께 사용함을 의미한다. 반면, 어떤 테이블은 더이상 변경, 삭제 작업이 없어, 최소의 디스크 공간만 사용하면 된다고 판단되면, VACUUM FULL 명령을 이용할 수도 있을 것이다. 이렇게 해서, 쓸모 없는 공간을 운영체제 쪽으로 반환할 수도 있다. 종합하면, 대용량 테이블을 관리하는 입장에서 보면, 비정기적인 VACUUM FULL 작업보다, 정기적인 표준 VACUUM 작업이 운영상 더 낫다.

어떤 관리자는 vacuum 작업을 사용량이 적은 밤 시간에 주기적으로 작업 하도록 직접 관리하려고 한다. 이렇게 특정 시간에 vacuum 작업을 할 때는 갑자기 자료 변경이 많은 작업이 생겨, 디스크 공간을 많이 쓰게 되는 경우도 함께 고려되어야 한다. 최악의 경우는 디스크 공간이 모자라 VACUUM FULL 작업을 선택해야 할 경우도 생기기 때문이다. autovacuum 데몬을 이용하면, 이런 예상치 못한 상황에 대해서도 자동으로 vacuum 작업이 진행되어 위와 같은 문제들을 피해갈 수 있다. 정확한 데이터베이스 사용량을 파악하지 않고 그냥 autovacuum 기능을 끄는 것은 현명하지 못한 선택이다. 한 타협점은 이 데몬의 실행 환경 설정값을 변경해서 예상치 못한 대량 변경 작업에 대해서만 vacuum 작업이 자동으로 실행 되겠끔 하는 것이다. 그래서, 주기적인 관리자 정의 VACUUM 작업을 유지하면서, 예외 상황에 대해서 자동으로 대처하도록 하는 것도 한 방법이 될 것이다.

autovacuum 기능을 사용하지 않는다면, 주의해야할 점은 해당 데이터베이스 서버에서 사용하고 있는 모든 데이터베이스에 대해서 VACUUM 작업을 해야한다는 것이다. 일반적으로 하루에 한 번 밤시간에 지정하는 것이 일반적이며, 자료가 빈번하게 변경되는 테이블에 대해서는 더 자주 vacuum 작업 하도록 설정한다. (아주 빈번한 테이블에 대해서 몇 분에 한 번씩 작업 하도록 설정해야할 필요도 있을 것이다.) 각 데이터베이스별 vacuum 작업을 할 때 vacuumdb 응용 프로그램을 이용하면 도움이 될 것이다.

작은 정보: 표준 VACUUM 작업은 해당 테이블 전체를 대상으로 하는 변경 작업이나, 삭제 작업과 같은 대량의 작업에 대해서는 만족할 만한 결과를 제공하지는 않는다. 이런 경우, 디스크 여유 공간을 확보해야 할 필요성이 있다면, VACUUM FULL 명령이나, CLUSTER 또는 ALTER TABLE 명령(CLUSTER ON 옵션)을 이용해서, 테이블을 아에 새롭게 만드는 방법을 선택할 수 있다. 이들 명령을 사용할 때는 반드시 주의해야할 사항은 이들 명령은 테이블 대상으로 배타적 잠금을 한다는 점이다. 즉, 이 작업이 완료되기 전까지 그 테이블을 대상으로 하는 다른 모든 작업들을 다른 세션에서는 할 수 없게 됨을 염두해 두어야 하며, 이들 작업은 작업 도중 원본과 다른 새로운 복사본 자료를 만들기 때문에 그만큼의 디스크 공간이 필요하다는 것도 기억하고 있어야 한다.

작은 정보: 테이블의 모든 자료를 아에 지워버리고자 한다면, DELETE 명령보다는 TRUNCATE 명령을 사용하는 것이 낫다. 이 명령은 작업 뒤에, VACUUM 이나 VACUUM FULL 명령을 사용할 필요가 없다. 단, 이 명령을 사용하게 되면 MVCC 대상에서 제외되기 때문에, 다중 세션 다중 트랜잭션 환경에서는 위험하다.

1.3. 실행계획 통계 정보 갱신

PostgreSQL 쿼리 실행 계획기는 쿼리의 좋은 실행 계획을 짜기 위해서 각 테이블에 저장된 자료를 바탕으로 수집된 통계 정보를 이용한다. 이 통계 정보는 ANALYZE 명령을 이용해서 만든다. 또한 VACUUM 명령을 수행하면서 옵션으로 이 작업을 할 수 있다. 이 통계 정보 갱신 작업이 제대로 되지 않으면 의도 되지 않은 쿼리 실행 계획이 짜여질 것이고, 이것으로 전체적으로 데이터베이스 성능을 떨어뜨리는 결과를 초래하기 때문에, 바른 통계 정보 갱신 작업을 주기적으로 하는 것은 중요하다.

autovacuum 기능을 이용한다면, 통계 정보를 갱신해야할 필요성이 있는 테이블들에 대해서 주기적으로 ANALYZE 명령을 자동으로 수행한다. 반면, 자료 변경 작업이 어떤 칼럼에 일어나고, 그 변경 작업 때문에, 통계 정보를 갱신해서, 실행 계획이 잘 짜여지는 것과 관련 없다고 명확하게 판단되는 경우라면, 관리자는 이 통계 정보 갱신 작업을 직접 수행하거나, 아에 안할 수도 있다. autovacuum 데몬은 이런 세세한 경우까지는 고려하지 않고, 테이블의 자료가 새로 추가 되었거나, 변경, 삭제 된 경우라면, 무조건 통계 정보 갱신 작업의 고려 대상이 된다고 판단한다.

통계 정보 갱신 작업도 디스크 여유 공간 확보를 위한 vacuum 작업과 마찬가지로 테이블의 자료 변화량이 많은 경우는 보다 빈번하게, 그 반대인 경우는 좀 더 드물게 진행됨이 좋다. 물론, 테이블의 자료가 빈번하게 변경된다고 하더라도, 그 변경 내용이 수집할 통계 정보와 관련 없는 것이라면, 당연히 통계 정보 갱신 작업이 필요 없다. 통계 정보를 갱신 할 빈도를 추측하는 가장 간단한 방법은 그 칼럼의 최소값과 최대값이 얼마나 자주 바뀌느냐를 살펴보는 것이다. 예를 들어 웹서비스에서 각 페이지의 마지막 접근 정보를 기록하는 테이블을 고려해 본다면, 마지막 접근 시각을 기록하는 timestamp 자료형의 칼럼은 URL을 담고 있는 칼럼보다 훨씬 빈번하게 변경될 것이다. 따라서 URL 정보의 통계 정보 갱신 작업보다 마지막 접근 시각의 통계 정보 갱신이 더 빈번하게 일어나야 보다 정확한 실행 계획이 짜여질 것이다.

ANALYZE 명령을 사용자가 직접 실행 할 때는, 한 테이블의 특정 칼럼 정보에 대해서만 통계 정보를 갱신하도록 할 수 있다. 이렇게 함으로 위에서 언급한 것 처럼 칼럼별 통계 정보 갱신 작업 빈도를 칼럼별로 조절할 수 있다. 하지만, 운영 환경에서는 일반적으로 데이터베이스 전체를 대상으로 이 작업을 한다. 왜냐하면, 기본적으로 자료 통계 정보 갱신 작업은 전체 자료를 대상으로 하지 않고, 임의의 샘플 자료만을 대상으로 하기 때문에, 꽤 빨리 작업이 끝난다.

작은 정보: 칼럼 단위로 ANALYZE 작업을 한다는 것이 운영 환경에서 사용하기에는 번거로운 일이긴 하지만, 보다 정확한 통계 정보를 싼 비용으로 갱신 할 수 있다는 점에서 장점이 있다. 예를 들어 한 칼럼의 자료 분포가 아주 넓고, 그 칼럼이 WHERE 절의 조건 검색으로 자주 사용된다면, 이 칼럼의 통계 정보는 다른 칼럼보다 더 꼼꼼하게 관리되는 것이 좋을 것이다. 이런 경우, ALTER TABLE SET STATISTICS 명령을 통해 해당 테이블의 개별 통계 수집 설정값을 바꾸어서 꼼꼼하게 관리 할 수 있다. 또한 서버 환경 설정인 default_statistics_target 값을 조정해서 데이터베이스 전체를 대상으로 조절할 수도 있다.

또한, 함수 사용에 대한 통계 정보는 기본적으로 제한된 정보만 제공 한다. 하지만, 함수 기반 인덱스를 만들었다면, 이 부분에 대해서는 통계 정보 갱신 작업이 함수 반환값을 대상으로 이루워 지기 때문에, 검색 조건으로 인덱스를 만들 때와 같이 해당 칼럼에 해당 함수를 사용하다면 쿼리 실행 계획기는 바르게 실행 계획을 짤 것이다.

작은 정보: autovacuum 데몬은 외부 테이블(foreign table)에 대해서는 ANALYZE 작업을 하지 않는다. 외부 테이블을 사용하고, 그것의 통계 정보가 갱신 될 필요성이 있다면, 직접 ANALYZE 명령을 주기적으로 실행해야 할 것이다.

 

 

출처 : http://postgresql.kr/docs/9.3/routine-vacuuming.html

by. 백준 (2014.11.24)