View a markdown version of this page

Aurora PostgreSQL의 일반적인 PostgreSQL 성능 문제에 대한 초기 문제 해결 - Amazon Aurora

Aurora PostgreSQL의 일반적인 PostgreSQL 성능 문제에 대한 초기 문제 해결

이 가이드에서는 Aurora PostgreSQL 데이터베이스에 영향을 미치는 가장 일반적인 네 가지 성능 문제, 즉 테이블 및 인덱스 팽창, 병렬 쿼리 리소스 소진, 높은 연결 및 인증 압력, autovacuum 조정을 다룹니다. 심층 조사를 시작하기 전에 성능 저하가 발생할 때 이 가이드를 1차 진단 체크리스트로 사용합니다.

각 섹션에서는 관찰할 수 있는 증상을 설명하고, 근본 원인을 확인하기 위한 진단 쿼리를 제공하고, 특정 문제 해결 단계를 권장합니다.

‘변경 없음’ 성능 회귀 이해

PostgreSQL 워크로드는 몇 주 또는 몇 달 동안 문제 없이 실행되는 경우가 많으며, 애플리케이션 코드와 쿼리 패턴이 변경되지 않은 것처럼 보이더라도 갑작스러운 성능 저하가 발생합니다. 이는 데이터베이스 환경이 정적이지 않기 때문에 발생합니다. 몇 가지 보이지 않는 요인이 시간이 지남에 따라 변화하여 계획 변경 또는 리소스 경합을 트리거할 수 있습니다.

  • 팽창 누적은 워크로드 변화입니다. PostgreSQL의 다중 버전 동시성 제어(MVCC)는 autovacuum이 회수할 때까지 이전 행 버전을 유지합니다. 데드 튜플이 autovacuum이 처리할 수 있는 것보다 빠르게 누적되면 테이블과 인덱스가 물리적으로 커집니다. 그러면 테이블 크기가 증가함에 따라 비용 추정치가 변화하기 때문에 쿼리 플래너가 효율적인 인덱스 스캔에서 순차적 스캔으로 전환할 수 있습니다. SQL은 변경되지 않았지만 플래너가 확인한 데이터는 변경되었습니다.

  • 새 파라미터 값은 워크로드 변경입니다. 한 값 범위에서 잘 작동하는 파라미터화된 쿼리는 애플리케이션이 다른 범위를 사용하기 시작할 때 성능이 저하될 수 있습니다. PostgreSQL은 새 범위의 데이터 스큐를 고려하지 않는 일반 실행 계획을 재사용하거나 플래너의 통계가 해당 값의 분포를 정확하게 반영하지 않을 수 있습니다. 팽창도 있는 경우 영향 구성 요소 - 최적이 아닌 계획은 이제 훨씬 더 많은 데드 데이터를 스캔합니다.

  • autovacuum이 실행되는 경우에도 통계가 오래된 상태일 수 있습니다. Autovacuum은 데이터 배포가 의미 있게 변경되었는지 여부가 아니라 삽입되거나 업데이트된 행 수를 ANALYZE 기반으로 트리거됩니다. 애플리케이션이 다른 값 범위 또는 기간을 쿼리하는 것으로 전환되는 경우, autovacuum이 최근에 실행되더라도 플래너의 비용 추정치가 부정확할 수 있습니다.

  • 전체 데이터베이스 증가는 워크로드 변화입니다. 시간이 지남에 따라 테이블이 증가함에 따라 쿼리가 스캔해야 하는 데이터 페이지의 양이 증가합니다. 작은 테이블에서 잘 수행된 쿼리는 쿼리 로직과 인덱스가 변경되지 않은 상태로 유지되더라도 테이블 크기가 증가함에 따라 지연 시간이 발생할 수 있습니다. VolumeBytesUsed를 모니터링하여 스토리지 성장 추세를 추적합니다.

‘아무것도 변하지 않음’인 성능 회귀를 조사할 때 팽창 누적, 새 파라미터 값 범위, 전체 데이터베이스 증가 및 기한 경과 통계를 가장 가능성이 높은 근본 원인으로 취급합니다. 이 가이드의 진단 단계를 사용하여 적용되는 요소를 확인합니다.

자세한 내용은 다음을 참조하세요.

빠른 진단 체크리스트

성능 문제를 처음 조사할 때 다음과 같이 순서가 지정된 분류 단계를 사용합니다.

  1. 을 검토합니다..pg_stat_activity 연결 수, 트랜잭션 내 유휴 세션 및 장기 실행 쿼리를 살펴봅니다. 자세한 내용은 Aurora PostgreSQL 조정의 필수 개념을 참조하세요.

  2. 팽창 여부를 확인합니다. pg_stat_user_tables에서 높은 n_dead_tup를 찾고 정확한 측정을 위해 pgstattuple을 사용하는 것이 좋습니다. 자세한 내용은 테이블 및 인덱스 팽창 진단를 참조하세요.

  3. 을 검토합니다..pg_stat_user_tables 높은 n_dead_tup 값과 오래된 last_autovacuum 타임스탬프를 찾습니다. 자세한 내용은 Aurora PostgreSQL에서 PostgreSQL autovacuum 작업을 참조하세요.

  4. 느린 쿼리에 대해 EXPLAIN ANALYZE를 검토합니다. 대형 테이블에서 병렬 계획과 순차 스캔을 찾습니다. 자세한 내용은 Aurora PostgreSQL의 병렬 쿼리 모범 사례를 참조하세요.

  5. CloudWatch 및 성능 개선 도우미 지표를 확인합니다. CPU 사용률, 연결 수, IOPS 및 사용 가능한 메모리를 검토합니다. 자세한 내용은 Amazon Aurora 모니터링을 참조하세요. 일반적인 대기 이벤트 및 수정 조치는 Aurora PostgreSQL 대기 이벤트를 참조하세요.

  6. DB 파라미터 그룹을 검토합니다. max_parallel_workers_per_gather 및 autovacuum 설정을 확인합니다. 자세한 내용은 Amazon RDS 및 Amazon Aurora에서 PostgreSQL 파라미터 조정을 참조하세요.

테이블 및 인덱스 팽창

테이블 및 인덱스 팽창은 autovacuum이 회수할 수 있는 것보다 빠르게 데드 튜플이 테이블에 누적될 때 발생합니다. 시간이 지남에 따라 점진적인 쿼리 성능 저하, 스토리지 사용량 증가 및 최적이 아닌 쿼리 계획이 발생합니다.

증상

  • 몇 주 또는 몇 달 동안의 점진적 쿼리 성능 저하

  • 안정적인 데이터 볼륨에도 불구하고 스토리지 사용량 증가

  • 쿼리 플래너는 기한 경과 통계로 인해 인덱스 스캔보다 순차적 스캔을 선택합니다.

  • 테이블 통계의 dead_tuple_count가 높음

진단

시스템 카탈로그를 쿼리하여 모든 테이블에서 팽창을 추정할 수 있습니다. 이 접근 방식에는 확장이 필요하지 않습니다.

SELECT schemaname, relname, n_dead_tup, n_live_tup, ROUND(n_dead_tup::numeric / GREATEST(n_live_tup, 1) * 100, 2) AS dead_pct, last_autovacuum, last_autoanalyze FROM pg_stat_user_tables WHERE n_dead_tup > 10000 ORDER BY n_dead_tup DESC LIMIT 20;

팽창을 해결하기 위해 pg_repack 확장을 사용하여 최소한의 잠금으로 테이블과 인덱스를 재구성할 수 있습니다. 자세한 내용은 pg_repack을 사용하여 테이블에서 팽창 제거pg_repack을 사용하여 Amazon Aurora 및 RDS for PostgreSQL에서 팽창 제거를 참조하세요.

중요

수동 유지 관리에 의존하는 대신 autovacuum이 활성화되어 있고 워크로드에 맞게 적절하게 조정되어 있는지 확인합니다. 조정 권장 사항은 Autovacuum 조정 섹션을 참조하세요.

병렬 쿼리 리소스 소진

PostgreSQL은 쿼리를 병렬로 실행하여 대규모 순차 스캔 및 집계의 성능을 개선할 수 있습니다. 그러나 각 병렬 작업자는 max_worker_processes(및 하위 제한 max_parallel_workers)에 대해 계산되고 자체 work_mem을 할당하는 전체 백엔드 프로세스입니다. 병렬 작업자가 4개인 단일 쿼리는 수백 메가바이트의 메모리와 상당한 CPU를 소비할 수 있습니다. 동시성이 높으면 과도한 병렬 처리로 인해 CPU와 메모리가 빠르게 소진될 수 있습니다.

일반적인 증상으로는 갑작스러운 CPU 스파이크, 쿼리당 높은 메모리 사용량, 애플리케이션 변경 없이 CloudWatch에서 DatabaseConnections 상승 등이 있습니다. IPC:BgWorkerStartup, IPC:ExecuteGatherIPC:ParallelFinish와 같은 대기 이벤트를 관찰할 수도 있습니다. 이러한 대기 이벤트에 대한 자세한 내용은 IPC:parallel 대기 이벤트를 참조하세요.

대부분의 OLTP 및 동시성이 높은 프로덕션 워크로드의 경우 DB 파라미터 그룹에서 max_parallel_workers_per_gather = 0을 설정하여 자동 병렬 처리를 비활성화합니다. 그런 다음 세션별 또는 역할별로 파라미터를 설정하여 특정 분석 또는 보고 세션에 대해 병렬 처리를 선택적으로 활성화할 수 있습니다.

병렬 쿼리 동작 진단 및 제어에 대한 자세한 지침은 Aurora PostgreSQL의 병렬 쿼리 모범 사례를 참조하세요.

높은 연결 및 인증 압력

풀링 없이 데이터베이스 연결을 자주 열고 닫는 연결 이탈은 인증 오버헤드를 발생시키고 사용 가능한 연결 슬롯을 소진할 수 있습니다. 열린 상태로 남아 있는 유휴 연결은 유용한 작업을 수행하지 않고 슬롯도 사용합니다.

증상

  • 성능 개선 도우미 모니터링에서 승격된 total_auth_attempts. 자세한 내용은 Aurora PostgreSQL용 비네이티브 카운터를 참조하세요.

  • 느린 연결 설정 시간

  • FATAL: too many connections for role 또는 remaining connection slots are reserved 오류

  • 연결 이탈과 상관관계가 있는 CPU 스파이크

진단

다음 쿼리를 실행하여 현재 연결 상태를 확인합니다.

SELECT setting::int AS max_connections, (SELECT count(*) FROM pg_stat_activity) AS current_connections, (SELECT count(*) FROM pg_stat_activity WHERE state = 'idle') AS idle_connections, (SELECT count(*) FROM pg_stat_activity WHERE state = 'idle in transaction') AS idle_in_txn FROM pg_settings WHERE name = 'max_connections';

max_connections에 대한 idle 또는 idle in transaction 연결 수가 많으면 연결이 제대로 해제되지 않았다는 의미입니다. 트랜잭션 내 유휴 연결은 잠금을 유지하고 autovacuum이 데드 튜플을 회수하지 못하도록 하기 때문에 특히 문제가 됩니다.

문제 해결

  • 연결 풀링을 배포합니다. PgBouncer 또는 Amazon RDS Proxy를 사용하여 데이터베이스에 대한 직접 연결 수를 줄입니다. 연결 풀링은 각 요청에 대해 새 연결을 생성하는 대신 기존 연결을 재사용합니다.

  • 을 설정합니다..idle_in_transaction_session_timeout 이 파라미터는 지정된 기간 이후에도 트랜잭션에서 유휴 상태로 유지되는 세션을 자동으로 종료합니다. 이렇게 하면 장기 실행 유휴 트랜잭션이 잠금을 유지하고 autovacuum을 차단하는 것을 방지할 수 있습니다.

  • 애플리케이션 연결 처리를 검토합니다. 애플리케이션이 연결을 즉시 닫고 필요 이상으로 트랜잭션을 열어 두지 않는지 확인합니다.

참고

병렬 쿼리 작업자는 CPU와 메모리를 사용합니다. 병렬 쿼리 활동과 함께 리소스 고갈이 관찰되면 병렬 쿼리 리소스 소진 섹션에서 병렬 작업자 사용량 제어에 대한 지침을 참조하세요.

문제 해결을 위해 성능 개선 도우미 대기 이벤트 사용

성능 개선 도우미는 데이터베이스가 시간을 소비하는 위치를 보여 주는 대기 이벤트를 캡처합니다. 성능 문제를 조사할 때 대기 이벤트는 병목 현상이 CPU, I/O, 잠금, 네트워크 또는 프로세스 간 통신인지 식별하는 데 도움이 됩니다. 이 가이드에 설명된 문제 중에 나타나는 일반적인 대기 이벤트 범주는 다음과 같습니다.

  • CPU - 세션이 CPU에서 활성 상태이거나 CPU를 기다리고 있습니다. CPU 대기 이벤트가 높으면 과도한 병렬 처리 또는 팽창된 테이블을 스캔하는 비효율적인 쿼리 계획과 상관관계가 있는 경우가 많습니다.

  • IPC(프로세스 간 통신) - IPC:BgWorkerStartup, IPC:ExecuteGatherIPC:ParallelFinish와 같은 대기 이벤트는 병렬 쿼리 조정 오버헤드를 나타냅니다.

  • IO - IO:DataFileRead와 같은 대기 이벤트는 필요한 페이지가 공유 메모리에 없기 때문에 쿼리가 스토리지에서 데이터를 읽고 있음을 나타냅니다. 이는 팽창된 테이블이 버퍼 캐시를 초과할 때 흔히 발생합니다.

  • 잠금 - Lock:transactionidLock:tuple과 같은 이벤트를 대기하고 세션 간 경합을 나타냅니다. 트랜잭션 내 유휴 연결에는 다른 쿼리와 autovacuum을 차단하는 잠금이 있을 수 있습니다.

  • 클라이언트 - 데이터베이스가 애플리케이션이 데이터를 전송할 때까지 대기 중임을 나타내는 Client:ClientRead 등의 이벤트를 기다립니다. 클라이언트 대기 이벤트가 높으면 연결 이탈 또는 네트워크 지연 시간을 나타낼 수 있습니다.

일반적으로 성능 문제를 나타내는 대기 이벤트와 권장 수정 조치에 대한 전체 참조는 Aurora PostgreSQL 대기 이벤트를 참조하세요.

Autovacuum 조정

Autovacuum은 데드 튜플을 회수하고, 테이블 및 인덱스 팽창을 방지하고, 플래너 통계를 업데이트하고, 트랜잭션 ID 랩어라운드로부터 보호하는 백그라운드 프로세스입니다. 기본 autovacuum 설정은 보수적이며 소규모 데이터베이스에 맞게 설계되었습니다. 쓰기 처리량이 높은 프로덕션 워크로드에는 거의 항상 조정이 필요합니다.

autovacuum이 쓰기 워크로드를 따라잡을 수 없는 경우 팽창이 누적되고 플래너 통계가 오래되고 트랜잭션 ID 랩어라운드 위험이 증가합니다. age(relfrozenxid)가 20억에 가까워지면 데이터 손상을 방지하기 위해 데이터베이스가 종료됩니다.

Autovacuum 파라미터 조정, vacuum 활동 모니터링 및 테이블별 재정의 구성에 대한 자세한 지침은 Aurora PostgreSQL에서 PostgreSQL autovacuum 작업을 참조하세요.

관련 정보