RDS for PostgreSQL의 vacuum 성능 문제 해결 - Amazon Relational Database Service

RDS for PostgreSQL의 vacuum 성능 문제 해결

이 섹션에서는 느린 vacuum 성능에 영향을 미치는 요인과 이러한 문제를 해결하는 방법을 설명합니다.

큰 인덱스 vacuum

VACUUM 프로세스는 초기화, 힙 스캔, 인덱스 및 힙 vacuum, 인덱스 정리, 힙 잘라내기, 최종 정리 수행 등의 여러 단계로 구성됩니다. 스캔 중에 페이지가 정리되고, 조각 모음되고, 고정됩니다. 힙이 완전히 스캔되면 인덱스가 정리되고 빈 페이지가 운영 체제로 반환되며 빈 공간 맵 vacuum 및 통계 업데이트와 같은 최종 정리 작업이 완료됩니다.

인덱스를 vacuum할 때 사용 가능한 maintenance_work_mem(또는 autovacuum_work_mem)이 인덱스를 처리하기에 충분하지 않은 경우 여러 번 전달해야 할 수 있습니다. PostgreSQL 버전 16 이하에서는 데드 튜플 ID 저장을 위한 메모리 할당에 대해 1GB 제한이 있어 여러 번의 전달이 필요하며, 큰 인덱스인 경우에는 특히 그렇습니다. PostgreSQL 버전 17은 단일 할당 배열을 대체하는 동적 메모리 할당 시스템인 TidStore를 도입하여 이러한 제한 사항을 해결합니다. 이로 인해 1GB 제약이 제거되고 메모리 효율성이 향상되며 각 인덱스당 여러 번 스캔할 가능성이 줄어듭니다.

그러나 PostgreSQL 17에서도 사용 가능한 메모리가 전체 인덱스를 한 번에 처리하기에 충분하지 않은 경우 큰 인덱스에 대해 여러 번 전달해야 할 수 있습니다. 일반적으로 큰 인덱스에는 여러 번 전달해야 하는 데드 튜플이 더 많이 포함되는 경향이 있습니다.

느린 vacuum 작업 탐지

postgres_get_av_diag() 함수는 메모리 부족으로 인해 vacuum 작업이 느리게 실행되는 시기를 탐지할 수 있습니다. 이 함수에 대한 자세한 내용은 RDS for PostgreSQL에 autovacuum 모니터링 및 진단 도구 설치 단원을 참조하십시오.

사용 가능한 메모리가 단일 패스에서 인덱스 vacuuming을 완료하기에 충분하지 않은 경우 postgres_get_av_diag() 함수는 다음 알림을 발행합니다.

rds_tools 1.8

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_work_mem is "XXX" and might not be sufficient. Consider increasing the setting, and if necessary, scaling up the Amazon RDS instance class for more memory. 
        Additionally, review the possibility of manual vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;).

rds_tools 1.9

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_work_mem is XX might not be sufficient. Consider increasing the setting to XXX, and if necessary, scaling up the RDS instance class for more 
        memory. The suggested value is an estimate based on the current number of dead tuples for the table being vacuumed, which might not fully reflect the latest state. Additionally, review the possibility of manual 
        vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;). For more information, see Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide.
참고

postgres_get_av_diag() 함수는 인덱스 vacuum 작업에 필요한 메모리의 양을 추정하기 위해 pg_stat_all_tables.n_dead_tup에 의존합니다.

postgres_get_av_diag() 함수가 autovacuum_work_mem 부족으로 인해 여러 인덱스 스캔이 필요한 느린 vacuum 작업을 식별하면 다음 메시지가 생성됩니다.

NOTICE: Your vacuum is performing multiple index scans due to insufficient autovacuum_work_mem:XXX for index vacuuming. 
        For more information, see Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide.

지침

수동 VACUUM FREEZE를 사용해 다음 해결 방법을 적용하여 테이블 고정의 속도를 높일 수 있습니다.

Vacuum 작업을 위한 메모리 증가

postgres_get_av_diag() 함수에서 제안한 대로 인스턴스 수준에서 잠재적 메모리 제약을 해결하기 위해 autovacuum_work_mem 파라미터를 늘리는 것이 좋습니다. autovacuum_work_mem은 동적 파라미터이지만 새 메모리 설정이 적용되려면 autovacuum 대몬이 작업자를 다시 시작해야 합니다. 이를 수행하는 방법은 다음과 같습니다.

  1. 새 설정이 있는지 확인합니다.

  2. 현재 autovacuum을 실행 중인 프로세스를 종료합니다.

이 접근 방식을 사용하면 조정된 메모리 할당이 새 autovacuum 작업에 적용됩니다.

보다 즉각적인 결과를 얻으려면 세션 내에서 maintenance_work_mem 설정이 증가된 VACUUM FREEZE 작업을 수동으로 수행하는 것을 고려하세요.

SET maintenance_work_mem TO '1GB'; VACUUM FREEZE VERBOSE table_name;

Amazon RDS를 사용하고 있고 maintenance_work_mem 또는 autovacuum_work_mem에 대해 더 높은 값을 지원하는 데 추가 메모리가 필요한 경우 메모리가 더 많은 인스턴스 클래스로 업그레이드하는 것을 고려해 보세요. 이를 통해 수동 및 자동 vacuum 작업을 모두 개선하는 데 필요한 리소스를 제공하여 전반적인 vacuum 및 데이터베이스 성능을 개선할 수 있습니다.

INDEX_CLEANUP 비활성화

PostgreSQL 버전 12 이상의 수동 VACUUM에서는 인덱스 정리 단계를 건너뛸 수 있고, PostgreSQL 버전 14 이상의 긴급 autovacuum에서는 vacuum_failsafe_age 파라미터를 기반으로 자동으로 이 작업을 수행합니다.

주의

인덱스 정리를 건너뛰면 인덱스 팽창이 발생하여 쿼리 성능에 부정적인 영향을 미칠 수 있습니다. 이를 완화하려면 영향을 받는 인덱스를 유지 관리 기간 동안 다시 인덱싱하거나 vacuum하는 것이 좋습니다.

큰 인덱스 처리에 대한 추가 지침은 대용량 인덱스를 사용하여 autovacuum 관리 의 설명서를 참조하세요.

병렬 인덱스 vacuum 작업

PostgreSQL 13부터 인덱스는 각 인덱스에 하나의 vacuum 작업자 프로세스가 할당된 수동 VACUUM을 사용하여 기본적으로 병렬로 vacuum 및 정리가 가능합니다. 그러나 vacuum 작업이 병렬 실행에 적합한지 PostgreSQL이 확인하려면 다음과 같은 특정 기준을 충족해야 합니다.

  • 인덱스가 최소 2개 있어야 합니다.

  • max_parallel_maintenance_workers 파라미터 값을 최소 2로 설정합니다.

  • 인덱스 크기는 min_parallel_index_scan_size 한도를 초과해야 하며, 기본값은 512KB입니다.

Amazon RDS 인스턴스에서 사용할 수 vCPU의 수와 테이블의 인덱스 수에 따라 max_parallel_maintenance_workers 설정을 조정하여 vacuum 작업 처리 시간을 최적화할 수 있습니다.

자세한 내용은 Parallel vacuuming in Amazon RDS for PostgreSQL and Amazon Aurora PostgreSQL을 참조하세요.

테이블 또는 데이터베이스가 너무 많아 vacuum 작업을 할 수 없음

PostgreSQL의 The Autovacuum Daemon 설명서에서 언급한 것처럼 autovacuum 대몬은 여러 프로세스를 통해 작동합니다. 여기에는 시스템 내 각 데이터베이스에 대해 autovacuum 작업자 프로세스를 시작하는 영구 autovacuum 런처가 포함됩니다. 런처는 데이터베이스당 약 autovacuum_naptime초마다 이러한 작업자가 시작하도록 일정을 예약합니다.

데이터베이스가 'N'개이면 새 작업자가 대략 [autovacuum_naptime/N초]마다 시작합니다. 그러나 총 동시 작업자 수는 autovacuum_max_workers 설정에 따라 제한됩니다. Vacuum 작업이 필요한 데이터베이스 또는 테이블 수가 이 한도를 초과하는 경우 작업자를 사용할 수 있게 되는 즉시 다음 데이터베이스 또는 테이블이 처리됩니다.

많은 대형 테이블 또는 데이터베이스에서 동시에 vacuum 작업이 필요한 경우 사용 가능한 모든 autovacuum 작업자가 장기간 점유되어 다른 테이블 및 데이터베이스에 대한 유지 관리가 지연될 수 있습니다. 트랜잭션 속도가 높은 환경에서는 이 병목 현상이 빠르게 에스컬레이션되어 Amazon RDS 인스턴스 내에서 vacuum 랩어라운드 문제가 발생할 수 있습니다.

postgres_get_av_diag()가 많은 수의 테이블 또는 데이터베이스를 감지하면 다음과 같은 권장 사항을 제공합니다.

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
NOTICE: The current setting of autovacuum_max_workers:3 might not be sufficient. Consider increasing the setting and, if necessary, consider scaling up the Amazon RDS instance class for more workers.

지침

autovacuum_max_workers 증가

Vacuum 작업의 속도를 높이기 위해 더 많은 동시 autovacuum 작업자를 허용하도록 autovacuum_max_workers 파라미터를 조정하는 것이 좋습니다. 성능 병목 현상이 지속되면 Amazon RDS 인스턴스를 더 많은 vCPU가 있는 클래스로 스케일 업하는 것이 좋습니다. 이렇게 하면 병렬 처리 기능을 더욱 개선할 수 있습니다.

공격적 vacuum(랩어라운드 방지용) 실행 중

PostgreSQL의 데이터베이스(MaximumUsedTransactionIDs) 연령은 공격적 vacuum(랩어라운드 방지용)이 성공적으로 완료될 때만 감소합니다. 이 vacuum 작업이 완료될 때까지 트랜잭션 속도에 따라 연령이 계속 증가합니다.

postgres_get_av_diag() 함수는 공격적인 vacuum을 감지하면 다음 NOTICE를 생성합니다. 그러나 vacuum의 활성 상태가 최소 2분간 지속된 후에만 이 출력이 트리거됩니다.

NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.

공격적 vacuum에 대한 자세한 내용은 When an aggressive vacuum is already running 섹션을 참조하세요.

다음 쿼리를 사용하여 공격적인 vacuum이 진행 중인지 확인할 수 있습니다.

SELECT a.xact_start AS start_time, v.datname "database", a.query, a.wait_event, v.pid, v.phase, v.relid::regclass, pg_size_pretty(pg_relation_size(v.relid)) AS heap_size, ( SELECT string_agg(pg_size_pretty(pg_relation_size(i.indexrelid)) || ':' || i.indexrelid::regclass || chr(10), ', ') FROM pg_index i WHERE i.indrelid = v.relid ) AS index_sizes, trunc(v.heap_blks_scanned * 100 / NULLIF(v.heap_blks_total, 0)) AS step1_scan_pct, v.index_vacuum_count || '/' || ( SELECT count(*) FROM pg_index i WHERE i.indrelid = v.relid ) AS step2_vacuum_indexes, trunc(v.heap_blks_vacuumed * 100 / NULLIF(v.heap_blks_total, 0)) AS step3_vacuum_pct, age(CURRENT_TIMESTAMP, a.xact_start) AS total_time_spent_sofar FROM pg_stat_activity a INNER JOIN pg_stat_progress_vacuum v ON v.pid = a.pid;

출력의 쿼리 열을 확인하여 공격적인 vacuum(랩어라운드 방지용)인지 확인할 수 있습니다. '랩어라운드 방지용'이라는 문구는 공격적인 vacuum임을 나타냅니다.

query | autovacuum: VACUUM public.t3 (to prevent wraparound)

예를 들어, 트랜잭션 연령이 10억인 블로커가 있고 동일한 트랜잭션 연령에서 랩어라운드 방지용으로 공격적인 vacuum이 필요한 테이블이 있다고 가정해 보겠습니다. 또한 트랜잭션 연령이 7억 5,000만인 또 다른 블로커가 있습니다. 트랜잭션 연령이 1억인 블로커를 정리한 후에 트랜잭션 연령이 7억 5,000만으로 즉시 줄어들지 않습니다. 공격적인 vacuum이 필요한 테이블 또는 연령이 7억 5,000만이 넘는 트랜잭션이 완료될 때까지 트랜잭션 연령이 높게 유지됩니다. 이 기간 동안 PostgreSQL 클러스터의 트랜잭션 연령이 계속 증가합니다. Vacuum 프로세스가 완료되면 트랜잭션 연령이 7억 5,000만으로 감소하지만 추가 vacuum 작업이 완료될 때까지 다시 증가하기 시작합니다. 이 주기는 이러한 조건이 지속되는 한, 트랜잭션 연령이 결국 autovacuum_freeze_max_age에서 지정된 Amazon RDS 인스턴스에 대해 구성된 수준으로 떨어질 때까지 계속됩니다.