

 Amazon Redshift는 패치 198부터 새 Python UDF 생성을 더 이상 지원하지 않습니다. 기존 Python UDF는 2026년 6월 30일까지 계속 작동합니다. 자세한 내용은 [블로그 게시물](https://aws.amazon.com/blogs/big-data/amazon-redshift-python-user-defined-functions-will-reach-end-of-support-after-june-30-2026/)을 참조하세요.

# 쿼리 성능 개선
<a name="query-performance-improvement-opportunities"></a>

다음은 문제를 진단 및 해결하는 방법에 대한 설명과 함께 Amazon Redshift 쿼리 성능에 영향을 미치는 몇 가지 일반적인 문제입니다.

**Topics**
+ [테이블 통계 누락 또는 만료](#table-statistics-missing-or-out-of-date)
+ [중첩 루프](#nested-loop)
+ [해시 조인](#hash-join)
+ [고스트 행 또는 커밋되지 않은 행](#ghost-rows-or-uncommitted-rows)
+ [정렬되지 않았거나 잘못 정렬된 행](#unsorted-or-mis-sorted-rows)
+ [최적이 아닌 데이터 분산](#suboptimal-data-distribution)
+ [쿼리에 할당되는 메모리 부족](#insufficient-memory-allocated-to-the-query)
+ [최상이 아닌 WHERE 절](#suboptimal-WHERE-clause)
+ [불충분한 제한적 조건자](#insufficiently-restrictive-predicate)
+ [매우 큰 결과 집합](#very-large-result-set)
+ [큰 SELECT 목록](#large-SELECT-list)

## 테이블 통계 누락 또는 만료
<a name="table-statistics-missing-or-out-of-date"></a>

테이블 통계가 누락되었거나 이전 상태이면 다음과 같이 표시될 수 있습니다.
+ EXPLAIN 명령 결과의 경고 메시지
+ STL\$1ALERT\$1EVENT\$1LOG의 통계 누락 알림 이벤트. 자세한 내용은 [쿼리 알림 검토](c-reviewing-query-alerts.md) 섹션을 참조하세요.

이 문제를 해결하려면 [ANALYZE](r_ANALYZE.md)를 실행하세요.

## 중첩 루프
<a name="nested-loop"></a>

중첩 루프가 존재하는 경우 STL\$1ALERT\$1EVENT\$1LOG에 중첩 루프 알림 이벤트가 표시됩니다. 이러한 유형의 이벤트는 [중첩 루프가 포함된 쿼리 식별](identify-queries-with-nested-loops.md)에 있는 쿼리를 실행해도 식별할 수 있습니다. 자세한 내용은 [쿼리 알림 검토](c-reviewing-query-alerts.md) 섹션을 참조하세요.

이 문제를 해결하려면 쿼리에서 크로스 조인 유무를 살펴본 후 가능하다면 제거하세요. 크로스 조인은 조인 조건이 없기 때문에 두 테이블의 데카르트 곱이 발생하는 원인이 됩니다. 또한 일반적으로 중첩 루프 조인으로 실행되기 때문에 가능한 조인 유형 중에서 속도가 가장 느립니다.

## 해시 조인
<a name="hash-join"></a>

해시 조인이 존재하는 경우 다음과 같이 표시됩니다.
+ 쿼리 계획에 해시 및 해시 조인 작업이 존재합니다. 자세한 내용은 [쿼리 계획 분석](c-analyzing-the-query-plan.md) 섹션을 참조하세요.
+ SVL\$1QUERY\$1SUMMARY에 maxtime 값이 가장 높은 세그먼트의 HJOIN 단계가 존재합니다. 자세한 내용은 [SVL\$1QUERY\$1SUMMARY 뷰 사용](using-SVL-Query-Summary.md) 섹션을 참조하세요.

이 문제를 해결하려면 다음과 같이 두 가지 방법을 사용할 수 있습니다.
+ 가능하다면 쿼리를 재작성하여 병합 조인을 사용하세요. 분산 키인 동시에 정렬 키인 조인 열을 지정하면 가능합니다.
+ SVL\$1QUERY\$1SUMMARY에서 HJOIN 단계의 rows 필드 값이 쿼리에서 최종 RETURN 단계의 rows 값에 비해 매우 높은 경우에는 쿼리를 재작성하여 고유한 열을 기준으로 조인할 수 있는지 확인하세요. 쿼리가 기본 키 같이 고유한 열을 기준으로 조인되지 않으면 조인에 참여하는 행의 수가 늘어납니다.

## 고스트 행 또는 커밋되지 않은 행
<a name="ghost-rows-or-uncommitted-rows"></a>

고스트 행 또는 커밋되지 않은 행이 존재하면 고스트 행이 지나치게 많다는 것을 나타내는 알림 이벤트가 STL\$1ALERT\$1EVENT\$1LOG에 표시됩니다. 자세한 내용은 [쿼리 알림 검토](c-reviewing-query-alerts.md) 섹션을 참조하세요.

이 문제를 해결하려면 다음과 같이 두 가지 방법을 사용할 수 있습니다.
+ Amazon Redshift 콘솔의 [**로드(Loads)**] 탭에서 쿼리 테이블에 대한 활성 로드 작업을 확인합니다. 활성 로드 작업이 있으면 끝날 때까지 기다린 후 다른 작업을 시작하세요.
+ 활성 로드 작업이 없으면 쿼리 테이블에 대해 [VACUUM](r_VACUUM_command.md)을 실행하여 삭제된 행을 제거하세요.

## 정렬되지 않았거나 잘못 정렬된 행
<a name="unsorted-or-mis-sorted-rows"></a>

정렬되지 않았거나 잘못 정렬된 행이 존재하면 STL\$1ALERT\$1EVENT\$1LOG에 선택의 폭이 매우 제한적인 필터 알림 이벤트가 표시됩니다. 자세한 내용은 [쿼리 알림 검토](c-reviewing-query-alerts.md) 섹션을 참조하세요.

그 밖에 [데이터 스큐 또는 미정렬 행이 포함된 테이블 식별](identify-tables-with-data-skew-or-unsorted-rows.md)에 있는 쿼리를 실행하여 쿼리 테이블 중 정렬되지 않은 영역이 많은 테이블이 있는지 알아보는 방법도 있습니다.

이 문제를 해결하려면 다음과 같이 두 가지 방법을 사용할 수 있습니다.
+ 쿼리 테이블에 대해 [VACUUM](r_VACUUM_command.md)을 실행하여 행을 다시 정렬하세요.
+ 쿼리 테이블의 정렬 키에서 개선할 수 있는 점이 있는지 살펴보세요. 단, 무엇이든 변경하기 전에 이 쿼리의 성능과 다른 중요한 쿼리 및 전반 시스템을 비교하여 검토해야 합니다. 자세한 내용은 [정렬 키](t_Sorting_data.md) 섹션을 참조하세요.

## 최적이 아닌 데이터 분산
<a name="suboptimal-data-distribution"></a>

데이터 분산이 최적의 상태가 아니면 다음과 같이 표시됩니다.
+ 직렬 실행, 대량 브로드캐스팅 또는 대량 분산 알림 이벤트가 STL\$1ALERT\$1EVENT\$1LOG에 표시됩니다. 자세한 내용은 [쿼리 알림 검토](c-reviewing-query-alerts.md) 섹션을 참조하세요.
+ 임의 단계에서 조각이 처리하는 행의 수가 대략적으로 동일하지 않습니다. 자세한 내용은 [SVL\$1QUERY\$1REPORT 뷰 사용](using-SVL-Query-Report.md) 섹션을 참조하세요.
+ 임의 단계에서 조각이 처리하는 데 걸리는 시간이 대략적으로 동일하지 않습니다. 자세한 내용은 [SVL\$1QUERY\$1REPORT 뷰 사용](using-SVL-Query-Report.md) 섹션을 참조하세요.

위에서 설명한 것 중 하나라도 사실이 아니라면 [데이터 스큐 또는 미정렬 행이 포함된 테이블 식별](identify-tables-with-data-skew-or-unsorted-rows.md)에 있는 쿼리를 실행하여 쿼리 테이블 중 데이터 스큐가 발생하는 테이블이 있는지 살펴보는 방법도 있습니다.

이 문제를 해결하려면 쿼리의 테이블에 대한 배포 스타일을 검토하고 개선할 수 있는 점이 있는지 확인합니다. 단, 무엇이든 변경하기 전에 이 쿼리의 성능과 다른 중요한 쿼리 및 전반 시스템을 비교하여 검토해야 합니다. 자세한 내용은 [쿼리 최적화를 위한 데이터 배포](t_Distributing_data.md) 섹션을 참조하세요.

## 쿼리에 할당되는 메모리 부족
<a name="insufficient-memory-allocated-to-the-query"></a>

쿼리에 할당되는 메모리가 부족하면 SVL\$1QUERY\$1SUMMARY에 `is_diskbased` 값이 true인 단계가 표시됩니다. 자세한 내용은 [SVL\$1QUERY\$1SUMMARY 뷰 사용](using-SVL-Query-Summary.md) 섹션을 참조하세요.

이 문제를 해결하려면 사용할 쿼리 수를 일시적으로 늘려서 쿼리에 더 많은 메모리를 할당하세요. 워크로드 관리(WLM)는 대기열에 설정되어 있는 동시성 레벨과 동일하게 쿼리 대기열의 슬롯을 보유합니다. 예를 들어 동시성 레벨이 5인 대기열은 슬롯 수도 5개입니다. 대기열에 할당되는 메모리는 균일하게 각 슬롯으로 분할됩니다. 하나의 쿼리에 다수의 슬롯을 할당하면 해당 쿼리는 할당된 모든 슬롯의 메모리에 대한 액세스 권한을 갖게 됩니다. 쿼리에 사용할 슬롯 수를 일시적으로 늘리는 방법에 대한 자세한 내용은 [wlm\$1query\$1slot\$1count](r_wlm_query_slot_count.md) 섹션을 참조하세요.

## 최상이 아닌 WHERE 절
<a name="suboptimal-WHERE-clause"></a>

WHERE 절이 지나치게 많은 테이블 스캔을 초래하면 세그먼트에서 SCAN 단계가 `maxtime` 값이 가장 높은 것으로 SVL\$1QUERY\$1SUMMARY에 표시됩니다. 자세한 내용은 [SVL\$1QUERY\$1SUMMARY 뷰 사용](using-SVL-Query-Summary.md) 섹션을 참조하세요.

이 문제를 해결하려면 가장 큰 테이블의 기본 정렬 열을 기준으로 WHERE 절을 쿼리에 추가하세요. 이 방법은 스캔 시간을 최소화하는 효과가 있습니다. 자세한 내용은 [Amazon Redshift 테이블 설계 모범 사례](c_designing-tables-best-practices.md) 섹션을 참조하세요.

## 불충분한 제한적 조건자
<a name="insufficiently-restrictive-predicate"></a>

쿼리에 불충분한 제한적 조건자가 있는 경우에는 세그먼트에서 SCAN 단계가 `maxtime` 값이 가장 높은 것으로 SVL\$1QUERY\$1SUMMARY에 표시되는 동시에 SVL\$1QUERY\$1SUMMARY에서 SCAN 단계의 `rows` 값이 쿼리에서 최종 RETURN 단계의 `rows` 값에 비해 매우 높습니다. 자세한 내용은 [SVL\$1QUERY\$1SUMMARY 뷰 사용](using-SVL-Query-Summary.md) 섹션을 참조하세요.

이 문제를 해결하려면 쿼리에 조건자를 추가하거나, 혹은 기존 조건자의 제한을 높여서 출력 범위를 좁히세요.

## 매우 큰 결과 집합
<a name="very-large-result-set"></a>

쿼리가 매우 큰 결과 집합을 반환하는 경우에는 쿼리를 재작성하면서 [UNLOAD](r_UNLOAD.md)를 사용하여 결과를 Amazon S3에 작성하는 것이 좋습니다. 이 방법은 병렬 처리를 이용해 RETURN 단계의 성능을 개선하는 효과가 있습니다. 매우 큰 결과 집합의 유무를 확인하는 방법에 대한 자세한 내용은 [SVL\$1QUERY\$1SUMMARY 뷰 사용](using-SVL-Query-Summary.md) 섹션을 참조하세요.

## 큰 SELECT 목록
<a name="large-SELECT-list"></a>

쿼리의 SELECT 목록이 비정상적으로 큰 경우에는 어떤 단계에서든지(다른 단계와 비교하여) `bytes` 값이 `rows` 값에 비해 비교적 높은 것으로 SVL\$1QUERY\$1SUMMARY에 표시됩니다. 이렇게 `bytes` 값이 높으면 선택한 열이 많다는 것을 나타낼 수 있습니다. 자세한 내용은 [SVL\$1QUERY\$1SUMMARY 뷰 사용](using-SVL-Query-Summary.md) 섹션을 참조하세요.

이 문제를 해결하려면 선택한 열을 살펴보면서 제거할 수 있는 열이 있는지 확인하세요.