VACUUM — 데이터베이스 가비지 수집(및 선택적으로 분석)

VACUUM — 데이터베이스 가비지 수집(및 선택적으로 분석)

테이블에 쌓인 죽은 튜플(dead tuple)이 차지하는 저장 공간을 정리하고, 원하면 통계를 갱신해 쿼리 플래너가 더 나은 실행 계획을 세우도록 도와주는 유지보수 명령이에요.

출처: PostgreSQL 문서

본문

Synopsis

VACUUM [ ( option [, ...] ) ] [ table_and_columns [, ...] ]

where option can be one of:

    FULL [ boolean ]
    FREEZE [ boolean ]
    VERBOSE [ boolean ]
    ANALYZE [ boolean ]
    DISABLE_PAGE_SKIPPING [ boolean ]
    SKIP_LOCKED [ boolean ]
    INDEX_CLEANUP { AUTO | ON | OFF }
    PROCESS_MAIN [ boolean ]
    PROCESS_TOAST [ boolean ]
    TRUNCATE [ boolean ]
    PARALLEL integer
    SKIP_DATABASE_STATS [ boolean ]
    ONLY_DATABASE_STATS [ boolean ]
    BUFFER_USAGE_LIMIT size

and table_and_columns is:

    [ ONLY ] table_name [ * ] [ ( column_name [, ...] ) ]

설명 (Description)

VACUUM은 죽은 튜플이 차지하는 저장 공간을 회수해요. 정상적인 PostgreSQL 운영에서 삭제되거나 갱신으로 인해 구식이 된 튜플은 테이블에서 물리적으로 제거되지 않아요. VACUUM이 수행될 때까지 남아 있죠. 따라서 특히 자주 갱신되는 테이블에서는 주기적으로 VACUUM을 수행하는 것이 필요해요.

table_and_columns 목록이 없으면 VACUUM은 현재 데이터베이스에서 현재 사용자가 vacuum할 권한이 있는 모든 테이블과 구체화된 뷰(materialized view)를 처리해요. 목록이 있으면 VACUUM은 해당 테이블들만 처리해요.

VACUUM ANALYZE는 각 선택된 테이블에 대해 VACUUM을 수행한 다음 ANALYZE를 수행해요. 이는 일상적인 유지보수 스크립트에 편리한 결합 형태예요. 처리 과정에 대한 자세한 내용은 ANALYZE 문서를 참고하면 돼요.

일반 VACUUM(FULL 없이)은 단순히 공간을 회수해 재사용할 수 있게 해줘요. 이 형태의 명령은 배타적 잠금이 획득되지 않으므로 테이블의 정상적인 읽기/쓰기와 병렬로 동작할 수 있어요. 하지만 추가 공간은 (대부분의 경우) 운영 체제에 반환되지 않아요. 같은 테이블 내에서 재사용할 수 있게만 유지될 뿐이에요. 또한 인덱스를 처리하기 위해 여러 CPU를 활용할 수 있게 해줘요. 이 기능은 병렬 vacuum(parallel vacuum)으로 알려져 있어요. 이 기능을 비활성화하려면 PARALLEL 옵션을 사용해 병렬 워커를 0으로 지정하면 돼요. VACUUM FULL은 테이블의 전체 내용을 추가 공간 없이 새 디스크 파일로 재작성해서, 사용되지 않는 공간이 운영 체제에 반환되게 해요. 이 형태는 훨씬 느리고 처리 중인 각 테이블에 ACCESS EXCLUSIVE 잠금을 요구해요.

매개변수 (Parameters)

FULL

더 많은 공간을 회수할 수 있지만 훨씬 더 오래 걸리고 테이블을 배타적으로 잠그는 "full" vacuum을 선택해요. 이 방식은 테이블의 새 복사본을 작성하고 작업이 완료될 때까지 이전 복사본을 해제하지 않기 때문에 추가 디스크 공간도 요구해요. 보통 테이블 내부에서 상당한 양의 공간을 회수해야 할 때만 사용해야 해요. FREEZE

공격적인(aggressive) 튜플 "동결(freezing)"을 선택해요. FREEZE를 지정하는 것은 vacuum_freeze_min_age와 vacuum_freeze_table_age 매개변수를 0으로 설정한 상태로 VACUUM을 수행하는 것과 동등해요. 테이블이 재작성될 때는 항상 공격적인 동결이 수행되므로, 이 옵션은 FULL이 지정되면 중복돼요. VERBOSE

각 테이블에 대한 상세한 vacuum 활동 보고서를 INFO 레벨로 출력해요. ANALYZE

플래너가 쿼리를 실행하는 가장 효율적인 방법을 결정하는 데 사용하는 통계를 갱신해요. DISABLE_PAGE_SKIPPING

일반적으로 VACUUM은 가시성 맵(visibility map)을 기반으로 페이지를 건너뜁니다. 모든 튜플이 동결된 것으로 알려진 페이지는 항상 건너뛸 수 있고, 모든 튜플이 모든 트랜잭션에 보이는 것으로 알려진 페이지는 공격적인 vacuum을 수행할 때를 제외하면 건너뛸 수 있어요. 게다가 공격적인 vacuum을 수행할 때가 아니면, 다른 세션이 페이지 사용을 끝낼 때까지 기다리지 않기 위해 일부 페이지를 건너뛸 수도 있어요. 이 옵션은 모든 페이지 건너뛰기 동작을 비활성화하며, 데이터베이스 손상을 일으키는 하드웨어나 소프트웨어 문제가 있을 때만 발생해야 하는, 가시성 맵의 내용이 의심될 때만 사용하도록 의도됐어요. SKIP_LOCKED

VACUUM이 릴레이션(relation)에 대한 작업을 시작할 때 충돌하는 잠금이 해제되기를 기다리지 않아야 한다고 지정해요. 대기 없이 즉시 릴레이션을 잠글 수 없으면 그 릴레이션은 건너뛰어져요. 이 옵션을 써도 릴레이션의 인덱스를 열 때는 VACUUM이 여전히 차단될 수 있다는 점을 유의하세요. 또한 VACUUM ANALYZE는 파티션, 테이블 상속 자식, 그리고 일부 유형의 외부 테이블에서 샘플 행을 획득할 때 여전히 차단될 수 있어요. 그리고 VACUUM이 보통 지정된 파티션 테이블의 모든 파티션을 처리하지만, 이 옵션은 파티션 테이블에 충돌하는 잠금이 있으면 VACUUM이 모든 파티션을 건너뛰게 해요. INDEX_CLEANUP

일반적으로 테이블에 죽은 튜플이 아주 적으면 VACUUM은 인덱스 vacuum을 건너뛰어요. 그럴 때 테이블의 모든 인덱스를 처리하는 비용이 죽은 인덱스 튜플 제거의 이점을 크게 초과할 것으로 예상되기 때문이에요. 이 옵션은 죽은 튜플이 0개를 초과할 때 VACUUM이 인덱스를 처리하도록 강제하는 데 사용할 수 있어요. 기본값은 AUTO로, 적절할 때 VACUUM이 인덱스 vacuum을 건너뛸 수 있게 해줘요. INDEX_CLEANUPON으로 설정되면 VACUUM은 인덱스에서 모든 죽은 튜플을 보수적으로 제거해요. 이것은 표준 동작이었던 이전 PostgreSQL 릴리스와의 역호환성에 유용할 수 있어요.

INDEX_CLEANUP은 테이블에 죽은 튜플이 많더라도 VACUUM이 인덱스 vacuum을 항상 건너뛰도록 강제하려면 OFF로 설정할 수도 있어요. 이것은 임박한 트랜잭션 ID 래핑(wraparound)(24.1.5절 참고)을 피하기 위해 VACUUM을 가능한 한 빨리 실행해야 할 때 유용할 수 있어요. 하지만 vacuum_failsafe_age가 제어하는 래핑 방지(failsafe) 메커니즘은 일반적으로 트랜잭션 ID 래핑 실패를 피하기 위해 자동으로 발동하며 선호되어야 해요. 인덱스 정리가 정기적으로 수행되지 않으면 성능이 저하될 수 있어요. 테이블이 수정되면서 인덱스에 죽은 튜플이 쌓이고 인덱스 정리가 완료될 때까지 제거할 수 없는 죽은 라인 포인터(line pointers)가 테이블 자체에 쌓이기 때문이에요.

이 옵션은 인덱스가 없는 테이블에는 효과가 없고, FULL 옵션을 사용하면 무시돼요. 또한 트랜잭션 ID 래핑 방지 메커니즘에는 효과가 없어요. 그것이 발동되면 INDEX_CLEANUPON으로 설정되어 있어도 인덱스 vacuum을 건너뛰어요. PROCESS_MAIN

VACUUM이 메인 릴레이션을 처리하도록 시도해야 한다고 지정해요. 이것이 보통 원하는 동작이고 기본값이에요. 이 옵션을 false로 설정하는 것은 릴레이션의 해당 TOAST 테이블만 vacuum하면 될 때 유용할 수 있어요. PROCESS_TOAST

VACUUM이 존재한다면 각 릴레이션의 해당 TOAST 테이블을 처리하도록 시도해야 한다고 지정해요. 이것이 보통 원하는 동작이고 기본값이에요. 이 옵션을 false로 설정하는 것은 메인 릴레이션만 vacuum하면 될 때 유용할 수 있어요. FULL 옵션을 사용할 때는 이 옵션이 필요해요. TRUNCATE

VACUUM이 테이블 끝에 있는 빈 페이지들을 잘라내고 잘라낸 페이지에 대한 디스크 공간이 운영 체제에 반환되도록 시도해야 한다고 지정해요. 이는 보통 원하는 동작으로, vacuum_truncate가 false로 설정되거나 vacuum할 테이블에 대해 vacuum_truncate 옵션이 false로 설정되지 않았다면 기본값이에요. 이 옵션을 false로 설정하는 것은 잘라내기가 요구하는 테이블에 대한 ACCESS EXCLUSIVE 잠금을 피하는 데 유용할 수 있어요. 이 옵션은 FULL 옵션을 사용하면 무시돼요. PARALLEL

integer개의 백그라운드 워커를 사용해 VACUUM의 인덱스 vacuum 및 인덱스 정리 단계를 병렬로 수행해요(각 vacuum 단계의 자세한 내용은 27.46 표를 참고). 작업 수행에 사용되는 워커 수는 병렬 vacuum을 지원하는 릴레이션의 인덱스 수와 같으며, PARALLEL 옵션으로 지정된 워커 수(있다면)에 의해 제한되고, 다시 max_parallel_maintenance_workers에 의해 제한돼요. 인덱스의 크기가 min_parallel_index_scan_size보다 큰 경우에만 인덱스가 병렬 vacuum에 참여할 수 있어요. 실행 중 integer에 지정된 병렬 워커 수가 사용된다는 보장은 없다는 점을 유의하세요. 지정된 것보다 적은 워커로, 심지어 워커 없이 vacuum이 실행될 수도 있어요. 인덱스당 하나의 워커만 사용할 수 있어요. 따라서 테이블에 인덱스가 2개 이상일 때만 병렬 워커가 시작돼요. vacuum용 워커는 각 단계가 시작되기 전에 시작되고 단계가 끝날 때 종료돼요. 이런 동작은 향후 릴리스에서 바뀔 수 있어요. 이 옵션은 FULL 옵션과 함께 사용할 수 없어요. SKIP_DATABASE_STATS

VACUUM이 가장 오래된 동결되지 않은 XID에 대한 데이터베이스 전체 통계 갱신을 건너뛰어야 한다고 지정해요. 일반적으로 VACUUM은 명령 끝에 이 통계를 한 번 갱신해요. 하지만 테이블 수가 매우 많은 데이터베이스에서는 시간이 걸릴 수 있고, 가장 오래된 동결되지 않은 XID를 포함했던 테이블이 vacuum된 테이블 중에 없으면 아무런 효과가 없어요. 게다가 여러 VACUUM 명령이 병렬로 발행되면 그중 하나만 동시에 데이터베이스 전체 통계를 갱신할 수 있어요. 따라서 애플리케이션이 많은 VACUUM 명령을 연속으로 발행하려 한다면, 마지막 명령을 제외한 모든 명령에 이 옵션을 설정하거나, 모든 명령에 설정하고 이후에 별도로 VACUUM (ONLY_DATABASE_STATS)를 발행하는 것이 도움이 될 수 있어요. ONLY_DATABASE_STATS

VACUUM이 가장 오래된 동결되지 않은 XID에 대한 데이터베이스 전체 통계 갱신만 하고 다른 일은 하지 않아야 한다고 지정해요. 이 옵션이 지정되면 table_and_columns 목록은 비어 있어야 하고, VERBOSE를 제외한 다른 옵션은 활성화될 수 없어요. BUFFER_USAGE_LIMIT

VACUUM을 위한 Buffer Access Strategy 링 버퍼 크기를 지정해요. 이 크기는 이 전략의 일부로 재사용될 공유 버퍼 수를 계산하는 데 사용돼요. 0Buffer Access Strategy 사용을 비활성화해요. ANALYZE도 지정되면 BUFFER_USAGE_LIMIT 값은 vacuum과 analyze 단계 모두에 사용돼요. 이 옵션은 ANALYZE도 지정되지 않으면 FULL 옵션과 함께 사용할 수 없어요. 이 옵션이 지정되지 않으면 VACUUM은 vacuum_buffer_usage_limit의 값을 사용해요. 더 높은 설정은 VACUUM이 더 빨리 실행되게 할 수 있지만, 너무 큰 설정은 너무 많은 유용한 페이지가 공유 버퍼에서 축출되게 할 수 있어요. 최솟값은 128 kB이고 최댓값은 16 GB예요. boolean

선택된 옵션을 켤지 끌지를 지정해요. 옵션을 활성화하려면 TRUE, ON, 또는 1을, 비활성화하려면 FALSE, OFF, 또는 0을 작성할 수 있어요. boolean 값은 생략할 수도 있는데, 그 경우 TRUE로 가정돼요. integer

선택된 옵션에 전달될 음이 아닌 정수 값을 지정해요. size

킬로바이트 단위의 메모리 양을 지정해요. 크기는 숫자 크기 뒤에 다음 메모리 단위 중 하나가 붙은 문자열로도 지정할 수 있어요. B(바이트), kB(킬로바이트), MB(메가바이트), GB(기가바이트), 또는 TB(테라바이트).

table_name

vacuum할 특정 테이블 또는 구체화된 뷰의 이름(선택적으로 스키마로 한정됨)이에요. 테이블 이름 앞에 ONLY가 지정되면 해당 테이블만 vacuum돼요. ONLY가 지정되지 않으면 테이블과 모든 상속 자식 테이블 또는 파티션(있다면)도 vacuum돼요. 선택적으로 테이블 이름 뒤에 *를 지정해 상속 자식 테이블(또는 파티션)이 vacuum될 것임을 명시적으로 나타낼 수 있어요. column_name

분석할 특정 컬럼의 이름이에요. 기본값은 모든 컬럼이에요. 컬럼 목록이 지정되면 ANALYZE도 지정해야 해요.

출력 (Outputs)

VERBOSE가 지정되면 VACUUM은 현재 어떤 테이블이 처리 중인지 나타내는 진행 메시지를 내보내요. 테이블에 대한 다양한 통계도 함께 출력돼요.

참고 (Notes)

테이블을 vacuum하려면 보통 그 테이블에 대한 MAINTAIN 권한이 있어야 해요. 하지만 데이터베이스 소유자는 공유 카탈로그를 제외한 자신의 데이터베이스에 있는 모든 테이블을 vacuum할 수 있어요. VACUUM은 호출한 사용자가 vacuum할 권한이 없는 테이블은 건너뛰어요.

VACUUM이 실행되는 동안 search_path는 일시적으로 pg_catalog, pg_temp로 변경돼요.

VACUUM은 트랜잭션 블록 안에서 실행할 수 없어요.

GIN 인덱스가 있는 테이블의 경우 VACUUM(모든 형태)은 보류 중인 인덱스 항목을 메인 GIN 인덱스 구조의 적절한 위치로 옮겨 보류 중인 인덱스 삽입도 완료해요. 자세한 내용은 65.4.4.1절을 참고하면 돼요.

죽은 행을 제거하기 위해 모든 데이터베이스를 정기적으로 vacuum할 것을 권장해요. PostgreSQL에는 일상적인 vacuum 유지보수를 자동화할 수 있는 "autovacuum" 기능이 포함되어 있어요. 자동 및 수동 vacuum에 대한 자세한 내용은 24.1절을 참고하면 돼요.

FULL 옵션은 일상적인 사용에는 권장되지 않지만 특별한 경우에는 유용할 수 있어요. 예를 들어 테이블의 대부분의 행을 삭제하거나 갱신했고 테이블이 물리적으로 줄어들어 디스크 공간을 덜 차지하고 더 빠른 테이블 스캔을 허용하기를 원할 때예요. VACUUM FULL은 보통 일반 VACUUM보다 테이블을 더 많이 줄여요.

PARALLEL 옵션은 vacuum 목적으로만 사용돼요. ANALYZE 옵션과 함께 지정되면 ANALYZE에는 영향을 미치지 않아요.

VACUUM은 I/O 트래픽을 상당히 증가시켜 다른 활성 세션의 성능 저하를 일으킬 수 있어요. 따라서 때로는 비용 기반 vacuum 지연 기능을 사용하는 것이 좋아요. 병렬 vacuum의 경우 각 워커는 해당 워커가 수행한 작업에 비례해 잠을 자요. 자세한 내용은 19.10.2절을 참고하면 돼요.

FULL 옵션 없이 VACUUM을 실행하는 각 백엔드는 pg_stat_progress_vacuum 뷰에 진행 상황을 보고해요. VACUUM FULL을 실행하는 백엔드는 대신 pg_stat_progress_cluster 뷰에 진행 상황을 보고해요. 자세한 내용은 27.4.5절과 27.4.2절을 참고하면 돼요.

예시 (Examples)

단일 테이블 onek을 정리하고, 최적화 프로그램을 위해 분석하고, 상세한 vacuum 활동 보고서를 출력해요:

VACUUM (VERBOSE, ANALYZE) onek;

호환성 (Compatibility)

SQL 표준에는 VACUUM 문이 없어요.

다음 구문은 PostgreSQL 버전 9.0 이전에 사용되었으며 여전히 지원돼요:

VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ table_and_columns [, ...] ]

이 구문에서는 옵션이 정확히 표시된 순서대로 지정되어야 한다는 점을 유의하세요.

더 알아보기 (Learn more)

  • 통계만 갱신하는 ANALYZE 명령과 함께 쓰는 경우가 많아요.
  • 테이블을 비우는 TRUNCATE와 행을 지우는 DELETE도 함께 알아두면 돼요.
  • 자동 vacuum 유지보수는 24.1절과 autovacuum 설정을 참고하면 돼요.
  • 진행 상황은 pg_stat_progress_vacuum 뷰에서 확인할 수 있어요.