Amazon Redshift에서 클러스터 또는 쿼리 성능 문제를 해결하려면 어떻게 해야 하나요?
Amazon Redshift 클러스터의 쿼리 성능 문제를 해결하거나 개선하고 싶습니다.
간략한 설명
Amazon Redshift 클러스터에서 성능 문제가 발생하는 경우 다음 작업을 완료하세요.
- 클러스터 성능 지표를 모니터링합니다.
- Amazon Redshift Advisor의 권장 사항을 확인합니다.
- 쿼리 실행 경고 및 과도한 디스크 사용량을 검토합니다.
- 잠금 문제 및 장기 실행 세션 또는 트랜잭션을 확인합니다.
- 워크로드 관리(WLM) 구성을 확인합니다.
- 클러스터 노드 하드웨어의 유지 관리 및 성능을 확인합니다.
해결 방법
클러스터 성능 지표 모니터링
클러스터 성능 지표와 그래프를 검토하면 성능 저하의 근본 원인을 찾는 데 도움이 됩니다. Amazon Redshift 콘솔에서 성능 데이터를 보고 시간 경과에 따른 클러스터 성능을 비교할 수 있습니다.
이러한 지표가 증가하면 Amazon Redshift 클러스터의 워크로드 및 리소스 경합이 더 심해지고 있음을 의미할 수 있습니다. 자세한 내용은 Amazon CloudWatch 지표를 사용한 Amazon Redshift 모니터링을 참조하세요.
Amazon Redshift 콘솔에서 워크로드 실행 내역을 확인하여 특정 쿼리와 런타임을 검토합니다. 예를 들어 쿼리 계획 시간이 늘어난다면 쿼리가 잠금을 기다리고 있는 것일 수 있습니다.
Amazon Redshift Advisor의 권장 사항 확인
Amazon Redshift Advisor 권장 사항을 사용하여 클러스터의 잠재적 개선 사항을 알아보세요. 권장 사항은 일반적인 사용 패턴과 Amazon Redshift 모범 사례를 기반으로 합니다.
쿼리 실행 경고 및 과도한 디스크 사용량 검토
쿼리가 실행되면 Amazon Redshift는 쿼리 성능을 기록하고 쿼리가 효율적으로 실행되고 있는지 여부를 표시합니다. 쿼리가 비효율적인 것으로 확인되면 Amazon Redshift는 쿼리 ID를 기록하고 쿼리 성능 개선을 위한 권장 사항을 제공합니다. 이러한 권장 사항은 STL_ALERT_EVENT_LOG 내부 시스템 테이블에 기록됩니다.
쿼리가 느리거나 비효율적인 경우 STL_ALERT_EVENT_LOG 항목을 확인합니다. STL_ALERT_EVENT_LOG 테이블에서 정보를 검색하려면 다음 쿼리를 실행합니다.
SELECT TRIM(s.perm_table_name) AS TABLE , (SUM(ABS(DATEDIFF(SECONDS, Coalesce(b.starttime, d.starttime, s.starttime), CASE WHEN COALESCE(b.endtime, d.endtime, s.endtime) > COALESCE(b.starttime, d.starttime, s.starttime) THEN COALESCE(b.endtime, d.endtime, s.endtime) ELSE COALESCE(b.starttime, d.starttime, s.starttime) END))) / 60)::NUMERIC(24, 0) AS minutes , SUM(COALESCE(b.ROWS, d.ROWS, s.ROWS)) AS ROWS , TRIM(SPLIT_PART(l.event, ':', 1)) AS event , SUBSTRING(TRIM(l.solution), 1, 60) AS solution , MAX(l.QUERY) AS sample_query , COUNT(DISTINCT l.QUERY) FROM STL_ALERT_EVENT_LOG AS l LEFT JOIN stl_scan AS s ON s.QUERY = l.QUERY AND s.slice = l.slice AND s.segment = l.segment LEFT JOIN stl_dist AS d ON d.QUERY = l.QUERY AND d.slice = l.slice AND d.segment = l.segment LEFT JOIN stl_bcast AS b ON b.QUERY = l.QUERY AND b.slice = l.slice AND b.segment = l.segment WHERE l.userid > 1 AND l.event_time >= DATEADD(DAY, -7, CURRENT_DATE) GROUP BY 1, 4, 5 ORDER BY 2 DESC, 6 DESC;
쿼리에는 쿼리 ID와 클러스터에서 실행 중인 쿼리에서 발생하는 가장 일반적인 문제가 나열됩니다.
다음은 알림이 트리거된 이유를 설명하는 쿼리 및 정보의 예제 출력입니다.
table | minutes | rows | event | solution | sample_query | count-------+---------+------+------------------------------------+--------------------------------------------------------+--------------+------- NULL | NULL | NULL | Nested Loop Join in the query plan | Review the join predicates to avoid Cartesian products | 1080906 | 2
쿼리 성능을 검토하려면 진단 쿼리에서 쿼리 조정을 확인하세요. 쿼리 작업이 효율적으로 실행되도록 설계되었는지 확인합니다. 예를 들어 모든 조인 작업이 효과적인 것은 아닙니다. 중첩 루프 조인은 효율성이 가장 낮은 조인 유형입니다. 중첩 루프 조인은 쿼리 런타임을 크게 증가시키므로 중첩 루프는 사용하지 않는 것이 좋습니다.
중첩 루프를 수행하는 쿼리를 식별하면 문제를 진단하는 데 도움이 됩니다. 자세한 내용은 Amazon Redshift를 사용하여 디스크 사용량이 많거나 꽉 차는 문제를 해결하려면 어떻게 해야 하나요?를 참조하세요.
잠금 문제 및 장기 실행 세션 또는 트랜잭션 확인
클러스터에서 쿼리를 실행하기 전에 Amazon Redshift는 쿼리 실행과 관련된 테이블에 대해 테이블 수준 잠금을 획득할 수 있습니다. 쿼리가 응답하지 않는 것처럼 보이거나 쿼리 런타임이 급증하는 경우가 있습니다. 쿼리 런타임이 급증하는 경우 잠금 문제가 급증의 원인일 수 있습니다. 자세한 내용은 Amazon Redshift에서 쿼리 계획 시간이 왜 이렇게 오래 걸리나요?를 참조하세요.
현재 다른 프로세스나 쿼리로 인해 테이블이 잠긴 경우 쿼리를 진행할 수 없습니다. 따라서 STV_INFLIGHT 테이블에 쿼리가 표시되지 않습니다. 대신 실행 중인 쿼리가 STV_RECENTS 테이블에 표시됩니다.
경우에 따라 트랜잭션이 오래 실행되면 쿼리가 응답하지 않을 수 있습니다. 장기 실행 세션이나 트랜잭션이 쿼리 성능에 영향을 주지 않도록 다음 작업을 수행하세요.
- STL_SESSIONS 및 SVV_TRANSACTIONS 테이블을 사용하여 장기 실행 세션 및 트랜잭션을 확인한 다음 종료합니다.
- Amazon Redshift에서 쿼리를 빠르고 효율적으로 처리할 수 있도록 쿼리를 설계합니다.
참고: 장기 실행 세션이나 트랜잭션은 디스크 공간을 회수하는 VACUUM 작업에도 영향을 주어 고스트 행 또는 커밋되지 않은 행의 수가 증가합니다. 쿼리가 스캔하는 고스트 행은 쿼리 성능에 영향을 줄 수 있습니다.
자세한 내용은 Amazon Redshift에서 잠금을 감지하고 해제하려면 어떻게 해야 하나요?를 참조하세요.
WLM 구성 확인
WLM 구성에 따라 쿼리가 즉시 실행되거나 일정 시간 동안 쿼리할 수 있습니다. 쿼리가 실행 대기열에 추가되는 시간을 최소화하세요. 대기열을 정의하려면 WLM 메모리 할당을 확인합니다.
며칠 동안 클러스터의 WLM 대기열을 확인하려면 다음 쿼리를 실행합니다.
SELECT *, pct_compile_time + pct_wlm_queue_time + pct_exec_only_time + pct_commit_queue_time + pct_commit_time AS total_pcntFROM (SELECT IQ.*, ((IQ.total_compile_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) AS pct_compile_time, ((IQ.wlm_queue_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) AS pct_wlm_queue_time, ((IQ.exec_only_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) AS pct_exec_only_time, ((IQ.commit_queue_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) pct_commit_queue_time, ((IQ.commit_time*1.0 / IQ.wlm_start_commit_time)*100)::DECIMAL(5,2) pct_commit_time FROM (SELECT trunc(d.service_class_start_time) AS DAY, d.service_class, d.node, COUNT(DISTINCT d.xid) AS count_all_xid, COUNT(DISTINCT d.xid) -COUNT(DISTINCT c.xid) AS count_readonly_xid, COUNT(DISTINCT c.xid) AS count_commit_xid, SUM(compile_us) AS total_compile_time, SUM(datediff (us,CASE WHEN d.service_class_start_time > compile_start THEN compile_start ELSE d.service_class_start_time END,d.queue_end_time)) AS wlm_queue_time, SUM(datediff (us,d.queue_end_time,d.service_class_end_time) - compile_us) AS exec_only_time, nvl(SUM(datediff (us,CASE WHEN node > -1 THEN c.startwork ELSE c.startqueue END,c.startwork)),0) commit_queue_time, nvl(SUM(datediff (us,c.startwork,c.endtime)),0) commit_time, SUM(datediff (us,CASE WHEN d.service_class_start_time > compile_start THEN compile_start ELSE d.service_class_start_time END,d.service_class_end_time) + CASE WHEN c.endtime IS NULL THEN 0 ELSE (datediff (us,CASE WHEN node > -1 THEN c.startwork ELSE c.startqueue END,c.endtime)) END) AS wlm_start_commit_time FROM (SELECT node, b.* FROM (SELECT -1 AS node UNION SELECT node FROM stv_slices) a, stl_wlm_query b WHERE queue_end_time > '2005-01-01' AND exec_start_time > '2005-01-01') d LEFT JOIN stl_commit_stats c USING (xid,node) JOIN (SELECT query, MIN(starttime) AS compile_start, SUM(datediff (us,starttime,endtime)) AS compile_us FROM svl_compile GROUP BY 1) e USING (query) WHERE d.xid > 0 AND d.service_class > 4 AND d.final_state <> 'Evicted' GROUP BY trunc(d.service_class_start_time), d.service_class, d.node ORDER BY trunc(d.service_class_start_time), d.service_class, d.node) IQ) WHERE node < 0 ORDER BY 1,2,3;
이 쿼리는 총 트랜잭션 수(xid), 런타임, 대기 시간, 커밋 대기열 세부 정보를 제공합니다. 커밋 대기열 세부 정보를 확인하여 빈번한 커밋이 워크로드 성능에 영향을 미치는지 확인하세요.
특정 시점에 실행 중인 쿼리의 세부 정보를 확인하려면 다음 쿼리를 실행하세요.
select b.userid,b.query,b.service_class,b.slot_count,b.xid,d.pid,d.aborted,a.compile_start,b.service_class_start_time,b.queue_end_time,b.service_class_end_time,c.startqueue as commit_startqueue,c.startwork as commit_startwork,c.endtime as commit_endtime,a.total_compile_time_s,datediff(s,b.service_class_start_time,b.queue_end_time) as wlm_queue_time_s,datediff(s,b.queue_end_time,b.service_class_end_time) as wlm_exec_time_s,datediff(s, c.startqueue, c.startwork) commit_queue_s,datediff(s, c.startwork, c.endtime) commit_time_s,undo_time_s,numtables_undone,datediff(s,a.compile_start,nvl(c.endtime,b.service_class_end_time)) total_query_s ,substring(d.querytxt,1,50) as querytext from (select query,min(starttime) as compile_start,max(endtime) as compile_end,sum(datediff(s,starttime,endtime)) as total_compile_time_s from svl_compile group by query) a left join stl_wlm_query b using (query) left join (select * from stl_commit_stats where node=-1) c using (xid) left join stl_query d using(query) left join (select xact_id_undone as xid,datediff(s,min(undo_start_ts),max(undo_end_ts)) as undo_time_s,count(distinct table_id) numtables_undone from stl_undone group by 1) e on b.xid=e.xid WHERE '2011-12-20 13:45:00' between compile_start and service_class_end_time;
참고: 2011-12-20 13:45:00을 대기열에 있거나 완료된 쿼리를 확인할 특정 시간 및 날짜로 바꿉니다.
클러스터 노드 하드웨어 성능 검토
클러스터 유지 관리 기간 중에 노드를 교체한 경우 클러스터를 곧 사용할 수 있습니다. 그러나 교체된 노드에서 데이터를 복원하는 데 시간이 다소 걸릴 수 있습니다. 이 프로세스 중에 클러스터 성능이 저하될 수 있습니다.
클러스터 성능에 영향을 미친 이벤트를 식별하려면 Amazon Redshift 클러스터 이벤트를 확인하세요.
데이터 복원 프로세스를 모니터링하려면 STV_UNDERREPPED_BLOCKS 테이블을 사용합니다. 다음 쿼리를 실행하여 데이터 복원이 필요한 블록을 검색하세요.
SELECT COUNT(1) FROM STV_UNDERREPPED_BLOCKS;
참고: 데이터 복원 프로세스 기간은 클러스터 워크로드에 따라 다릅니다. 클러스터의 데이터 복원 프로세스 진행 상황을 측정하려면 간격을 두고 블록을 확인하세요.
특정 노드의 상태를 확인하려면 다음 쿼리를 실행하여 해당 노드의 성능을 다른 노드와 비교합니다.
SELECT day , node , elapsed_time_s , sum_rows , kb , kb_s , rank() over (partition by day order by kb_s) AS rank FROM ( SELECT DATE_TRUNC('day',start_time) AS day , node , sum(elapsed_time)/1000000 AS elapsed_time_s , sum(rows) AS sum_rows , sum(bytes)/1024 AS kb , (sum(bytes)/1024)/(sum(elapsed_time)/1000000) AS "kb_s" FROM svl_query_report r , stv_slices AS s WHERE r.slice = s.slice AND elapsed_time > 1000000 GROUP BY day , node ORDER BY day , node );
쿼리 출력 예시:
day node elapsed_time_s sum_rows kb kb_s rank... 4/8/20 0 3390446 686216350489 21570133592 6362 4 4/8/20 2 3842928 729467918084 23701127411 6167 3 4/8/20 3 3178239 706508591176 22022404234 6929 7 4/8/20 5 3805884 834457007483 27278553088 7167 9 4/8/20 7 6242661 433353786914 19429840046 3112 1 4/8/20 8 3376325 761021567190 23802582380 7049 8
참고: 위 출력은 노드 7이 6242661초 동안 19429840046KB의 데이터를 처리했음을 보여줍니다. 이는 다른 노드보다 훨씬 느린 속도입니다.
sum_rows 열의 행 개수와 kb 열의 처리된 바이트 수 간의 비율은 거의 같습니다. 하드웨어 성능에 따라 kb_s 열의 행 개수도 sum_rows 열의 행 개수와 거의 같습니다. 노드가 일정 기간 동안 처리하는 데이터 양이 적으면 근본적인 하드웨어 문제가 있을 수 있습니다. 근본적인 하드웨어 문제가 있는지 확인하려면 노드의 성능 그래프를 검토합니다.
- 언어
- 한국어
