Amazon Redshift에서 높은 CPU 사용률 문제는 어떻게 해결합니까?

최종 업데이트 날짜: 2020년 8월 24일

갑자기 Amazon Redshift 클러스터의 CPU 사용률이 높습니다. CPU 사용률이 높아지는 이유는 무엇이며 사용률을 낮추는 모범 사례는 무엇입니까?

간략한 설명

Amazon Redshift는 쿼리를 수행하는 동안 사용 가능한 모든 리소스를 활용하도록 설계되었습니다. 따라서 Amazon Redshift 클러스터에서 CPU 사용률이 급증할 것으로 예상됩니다. CPU 사용률의 증가는 클러스터 워크로드, 편향된 데이터 및 정렬되지 않은 데이터 또는 리더 노드 작업과 같은 요소에 따라 달라질 수 있습니다.

그러나 CPU 사용률이 쿼리 시간에 영향을 주는 경우 다음 방법을 고려하십시오.

  • Amazon Redshift 클러스터 워크로드를 검토합니다.
  • 데이터를 정제된 상태로 유지합니다.
  • 테이블 디자인을 업데이트하십시오.
  • 유지 관리 업데이트를 확인합니다.
  • 리더 노드 CPU 사용률이 급증하는지 확인합니다.
  • Amazon CloudWatch를 사용하여 CPU 사용률의 급증을 모니터링할 수 있습니다.

​해결 방법

Amazon Redshift 클러스터 워크로드 검토

Amazon Redshift 클러스터의 CPU 사용률에 영향을 줄 수 있는 요소는 다음과 같습니다.

  • 실행 중인 쿼리가 더 많기 때문에 증가된 워크로드 워크로드가 증가하면 데이터베이스 연결 수가 증가하여 쿼리 동시성이 높아집니다.
  • 동시 쿼리 수가 많을수록 리소스 경합, 잠금 대기 시간 및 WLM (워크로드 관리) 대기열 대기 시간에도 영향을 줍니다.
  • 더 많은 데이터베이스 연결 - 클러스터에 유휴 세션이 있을 수도 있습니다. 유휴 세션은 추가적인 잠금 경합 문제를 일으킬 수 있습니다.

조회가 실행되는 동안 잠금 정보를 검색합니다. 장기 실행 세션을 식별하려면 다음 SQL 쿼리를 사용합니다.

select *,datediff(s,txn_start,getdate())/86400||' days '||datediff(s,txn_start,getdate())%86400/3600||' hrs '||datediff(s,txn_start,getdate())%3600/60||' mins '||datediff(s,txn_start,getdate())%60||' secs'
from svv_transactions where lockable_object_type='transactionid' and pid<>pg_backend_pid() order by 3;

그런 다음 장기 실행 트랜잭션을 중지하려면 PG_TERMINATE_BACKEND를 실행합니다. 이러한 세션이 열린 상태로 유지되는 것을 방지하려면 모든 트랜잭션이 닫혀 있어야 합니다. 예를 들어 BEGIN 문으로 시작하는 모든 트랜잭션에도 END 또는 COMMIT 문이 함께 제공되는지 확인합니다.

그런 다음 높은 CPU를 사용하는 쿼리를 식별하려면 다음 SQL 쿼리를 실행합니다.

select stq.userid, stq.query, trim(stq.label) as label, stq.xid, stq.pid, svq.service_class,
query_cpu_usage_percent as "cpu_%",starttime, endtime, datediff(s,starttime, endtime) as duration_s,
substring(stq.querytxt,1,100) as querytext from stl_query stq
join svl_query_metrics svq on stq.query=svq.query 
where query_cpu_usage_percent is not null and starttime > sysdate - 1
order by query_cpu_usage_percent desc;

각 쿼리에 대한 세그먼트 및 슬라이스 수준 실행 단계를 분석하려면 다음 쿼리를 실행합니다.

select query, segment, step, label ,is_rrscan as rrS, is_diskbased as disk, is_delayed_scan as DelayS, min(start_time) as starttime, max(end_time) as endtime, datediff(ms, min(start_time), max(end_time)) as "elapsed_msecs", sum(rows) as row_s , sum(rows_pre_filter) as rows_pf, CASE WHEN sum(rows_pre_filter) = 0 THEN 100 ELSE sum(rows)::float/sum(rows_pre_filter)::float*100 END as pct_filter, SUM(workmem)/1024/1024 as "Memory(MB)", SUM(bytes)/1024/1024 as "MB_produced" from svl_query_report where query in (<query_ids>) group by query, segment, step, label , is_rrscan, is_diskbased , is_delayed_scan order by query, segment, step, label;

이러한 쿼리 튜닝에 대한 자세한 내용은 Top 10 performance tuning techniques for Amazon Redshift를 참조하십시오.

또한 wlm_query_trend_hourly 보기를 사용하여 Amazon Redshift 클러스터 워크로드 패턴을 검토할 수도 있습니다. 그리고 다음 중 대기열 대기 시간을 줄이는 데 도움이 될 수 있는 방법을 결정합니다.

  • 대기열당 쿼리 동시성을 줄여 각 쿼리 슬롯에 더 많은 메모리를 제공합니다. 이 감소는 더 많은 메모리가 필요한 쿼리를 보다 효율적으로 실행하는 데 도움이 됩니다.
  • 짧은 쿼리 가속(SQA)을 사용하여 장기 실행 쿼리에 비해 단기 실행 쿼리를 우선 순위로 지정합니다.
  • 증가된 워크로드를 수용할 수 있도록 Amazon Redshift 클러스터를 확장합니다. 클러스터를 확장하면 더 많은 메모리와 컴퓨팅 성능이 제공되므로 쿼리를 더 빠르게 실행할 수 있습니다. 자세한 내용은 Amazon Redshift 클러스터의 크기를 조정하려면 어떻게 해야 합니까?를 참조하십시오.

데이터를 정제된 상태로 유지

정제된 데이터는 테이블에 존재하는 부실 통계 및 정렬되지 않은 행의 백분율로 측정됩니다. 두 개의 비율이 높으면 쿼리 최적화 프로그램이 테이블을 참조할 때 쿼리가 비효율적으로 실행되는 실행 계획을 생성할 수 있습니다. 정렬되지 않은 데이터는 쿼리가 추가 I/O 작업이 필요한 불필요한 데이터 블록을 검색할 수 있도록 합니다. 성능이 좋지 않은 쿼리는 클러스터의 CPU 사용률에 부정적인 영향을 미칩니다.

SVV_TABLE_INFO 시스템 보기를 사용하여 테이블에 대한 stats_offunsorted 백분율 데이터를 검색합니다. 이러한 백분율은 0에 가깝게 유지되어야 합니다. 비율이 높으면 AWS Labs GitHub 리포지토리에서 분석 및 진공 스키마 유틸리티를 실행하여 테이블을 업데이트합니다.

테이블 디자인 업데이트

테이블 디자인은 지정된 정렬 키, 배포 스타일 및 배포 키로 제어됩니다. 배포 키 및 배포 스타일은 데이터를 노드 전체에 분산하는 방법을 결정합니다.

부적절한 배포 키 또는 배포 스타일은 노드 전체에서 분포 왜곡을 유발할 수 있습니다. 데이터 분포 왜곡을 줄이려면 쿼리 패턴 및 조건자에 따라 적절한 배포 스타일정렬 키를 선택합니다. 배포 키는 높은 카디넬리티가 있는 쿼리 및 열에서 조인 조건을 지원해야 합니다. 적절한 배포 키 선택은 쿼리가 해시 또는 중첩 루프 조인 대신 병합 조인을 수행하는 데 도움이 될 수 있습니다. 이 조인은 궁극적으로 쿼리 실행 시간에 영향을 미칩니다.

분포가 치우친 테이블을 식별하려면 table_inspector.sql 스크립트를 사용합니다. 그런 다음 Amazon Redshift 테이블 디자인 플레이북을 사용하여 테이블에 가장 적합한 정렬 키, 배포 키 및 배포 스타일을 선택합니다.

유지 관리 업데이트 확인

Amazon Redshift는 컴파일된 코드를 캐시하므로 쿼리가 이전에 실행된 세그먼트에 코드를 재사용할 수 있습니다. 그러면 유지 관리 업데이트 중에 캐시가 지워집니다. 따라서 패치 업데이트 후 처음으로 실행되는 쿼리는 컴파일에 약간의 시간을 소비합니다. 이 컴파일 과부하는 클러스터의 CPU 사용률을 증가시킬 수 있습니다.

다음 SQL 쿼리를 사용하여 매시간 컴파일되는 세그먼트 수를 확인합니다.

select "hour", count(query) total_queries, count(case when is_compiled='Y' then 1 else null end ) as queries_compiled_count, sum(segements_count) total_segments_count, sum(segments_compiled_count) total_segments_compiled_count from
(
  select q.query, date_trunc('h',q.starttime) as "hour", q.starttime, q.endtime, q.aborted, (case when compiled_queries.segments_compiled_count = 0 then 'N' ELSE 'Y' end) is_compiled, compiled_queries.segements_count, compiled_queries.segments_compiled_count
  from stl_query q
  left join (select query, count(segment) segements_count, sum(compile) segments_compiled_count from svl_compile group by query) compiled_queries on q.query = compiled_queries.query
  where q.userid > 1
  and q.starttime > trunc(sysdate) -7
)
group by "hour"
order by "hour";

리더 노드 CPU 사용률 급증 확인

쿼리 구문 분석 및 최적화, 컴파일된 코드 생성, 컴퓨팅 노드의 결과 집계와 같은 리더 노드 작업은 CPU 리소스를 소비합니다. 이 소비는 리더 노드 CPU 사용률을 증가시킵니다. 쿼리가 시스템 카탈로그 테이블을 많이 참조하거나 리더 노드 전용 함수를 수행하는 경우에도 리더 노드 CPU 사용률이 증가할 수 있습니다.

리더 노드로 인해 CPU 사용률이 급증한 경우 Amazon Redshift 콘솔Events(이벤트) 아래에서 확인합니다. Amazon Redshift 클러스터에서 유지보수가 발생했는지 확인합니다. 유지 관리 업데이트 확인에 제공된 SQL 쿼리를 사용하여 평소보다 더 많은 세그먼트가 컴파일되고 있는지 확인합니다.

CloudWatch를 사용하여 CPU 사용률 급증 모니터링

CloudWatch 지표를 사용하여 CPU사용률데이터베이스 연결 간의 급증을 비교합니다. 워크로드 실행 분석 차트를 확인하여 워크로드 성능을 분석합니다. 워크로드 실행 분석 차트는 가장 많은 시간을 소비하는 쿼리 단계를 보여 줍니다.

지정된 시간 동안 CPU를 가장 많이 사용하는 상위 100개의 쿼리를 식별하려면 다음 쿼리를 사용합니다.

select qms.*, substring(q.querytxt,1,100) qtxt
from svl_query_metrics_summary qms
join stl_query q on q.query=qms.query
where q.starttime > sysdate - 1 
and q.userid>1
order by qms.query_cpu_time desc nulls last limit 100;

CPU가 100%에 도달할 때 리소스를 가장 많이 사용하는 쿼리 목록을 검색하려면 다음 쿼리를 사용합니다.

select a.userid, service_class, a.query, b.pid, b.xid, a.starttime, slices, max_rows, max_blocks_read, max_blocks_to_disk, max_query_scan_size, segment, round(max_cpu_time/(max_run_time*1.0)*100,2) as max_cpu_pcnt, round(cpu_time/(run_time*1.0)*100,2) as cpu_pcnt, max_cpu_time, max_run_time, case when segment > -1 then 'segment' else 'query' end as metric_lvl, text from pg_catalog.stv_query_metrics a left join stv_inflight b using (query) where step_type=-1 order by query, segment;

각 노드에서 처리되는 데이터의 양을 확인하려면 다음 쿼리를 실행 합니다.

select iq.day_d, sl.node, sum(iq.elapsed_ms) as elapsed, sum(iq.bytes) as bytes from (select start_time::date as day_d, slice,query,segment,datediff('ms',min(start_time),max(end_time)) as elapsed_ms, sum(bytes) as bytes from svl_query_report where end_time > start_time group by 1,2,3,4) iq join stv_slices as sl on (sl.slice = iq.slice) group by 1,2 order by 1 desc, 3 desc;  

쿼리 모니터링 규칙(QMR)을 사용하여 잘못 설계된 쿼리를 식별하고 기록할 수 있습니다. 예를 들어, QMR 규칙을 정의하여 CPU 사용률이 높거나 실행 시간이 연장되는 쿼리를 기록할 수 있습니다.


이 문서가 도움이 되었습니까?


결제 또는 기술 지원이 필요합니까?