AWS Athena 쿼리 성능 최적화하기

2026. 3. 16. 16:42·인프라/AWS
반응형

 

Athena에서 느린 쿼리, 리소스 초과 오류, 불필요한 비용

AWS 공식 문서를 바탕으로 Athena 쿼리를 더 빠르고 효율적으로 만드는 핵심 기법을 정리해보겠습니다.

 

색깔별 구분

  • Athena + RDB 범용적으로 적용 가능: 초록색
  • 부분적으로 RDB에도 적용 가능: 빨간색
  • Athena 전용(RDB는 해당 없음): 회색

 

1. 조인 순서: 큰 테이블을 왼쪽에

Athena는 분산 해시 조인을 실행할 때, 오른쪽 테이블을 빌드측으로 사용합니다.

이 해시 테이블이 메모리를 초과하면 쿼리가 실패합니다.

항상 작은 테이블을 JOIN 오른쪽에 배치합니다.

 

해시 조인이란?

두 테이블을 조인할 때, 가장 직관적인 방법은 모든 행을 일일이 비교하는 것입니다.

orders 100 만행 x customers 10만행 = 1,000억번 비교 -> 당연히 너무 느립니다. 

해시 조인이란 이 문제를 해결하는 방식인데, 사전(dictionary)을 만드는 것과 같습니다. 

작은 테이블(customers)로 먼저 '해시 테이블'이라는 조회표를 메모리에 만들어 두고, 큰 테이블(orders)을 한 줄씩 읽으면서 조회 표에서 찾습니다. 전화번호부를 처음부터 끝까지 찾는 대신, 이름 색인으로 바로 찾는 것과 같습니다. 

 

그래서 분산 해시 조인이란?

Athena는 데이터를 혼자 처리하는 게 아니라, 여러 워커 노드가 병렬로 처리합니다.

그래서 해시 테이블도 여러 노드에서 쪼개서 각자 만들고, 큰 테이블도 같은 규칙으로 쪼개서 각 노드가 자기 담당 조각만 조인합니다.

 

그래서 왜 '작은 테이블을 오른쪽에'가 중요할까?

빌드 측 (작은 테이블)의 해시 테이블은 각 노드의 메모리에 올라가야 합니다. 

만약 빌드 측이 너무 크면 메모리가 부족해서 쿼리가 실패합니다. 

Athena는 자동으로 작은 테이블을 빌드 측으로 쓰려고 하지만, 작성자가 직접 써줘야 할 떄도 있습니다. 

 

TIP) 빌드 측 크기를 메모리에 맞출 수 없다면, 빌드 테이블의 하위 세트를 나눠 여러번 조인하는 방식을 고려해볼 수 있어요.

 

2. 윈도우 함수 대신 집계 함수 사용

윈도우 함수는 모든 레코드를 유지하므로, `Query exhausted resources at this scale factor` 오류의 주범이 됩니다. 

row_number, rank대신 max_by, min_by, arbitrary같은 집계 함수를 활용하면 메모리 사용량을 크게 줄일 수 있습니다.

 

집계함수 vs 윈도우 함수

  • 집계함수 (GROUP BY와 함께)
  • 행을 합쳐서 줄임, 메모리 사용 적음
  • SUM, COUNT, MAX, max_by등이 해당
  • 그룹당 결과가 딱 1행 나옴.

 

윈도우 함수 (OVER와 함께)

  • 행을 유지하며 계산, 전체를 메모리에 보관
  • ROW_NUMBER(), RANK(), LAG()등이 해당
  • 5행이 들어오면 5행이 그대로 나오되, 순번같은 컬럼이 하나 추가됨

 

arbitrary()는 GROUP BY를 쓸 때 생기는 SQL 문법 제약을 피하기 위한 함수입니다. 

SELECT에 쓴 컬럼은 반드시 GROUP BY에 있거나 집계 함수로 감싸야 하는데, 특정 집계가 필요하지 않다면 arbitrary()로 묶어서 에러를 피할 수 있습니다. 메모리도 아끼고 오류도 없앨 수 있습니다.

 

SELECT 
    user_id, 
    MAX(order_date) as last_order,
    ARBITRARY(address) as any_address -- 사용자 주소가 여러 개여도 하나만 가져옴
FROM orders
GROUP BY user_id;

 

3. GROUP BY 절 최적화

GROUP BY 절에는 꼭 필요한 열만 포함해야 합니다. 

숫자는 문자열보다 메모리를 덜 사용합니다. 

그래서 카테고리 이름 대신, 카테고리 ID로 그룹화하는 것이 도움이 됩니다. 

쿼리 오류를 피하기 위해 GROUP BY에 추가하는 열은 arbitrary()함수로 대체할 수 있습니다.

 

4. 상위 N개 쿼리: ORDER BY + LIMIT

Athena는 ORDER BY와 LIMIT이 함께 사용될 때 전용 최적화 작업을 수행합니다. 

따라서 최근 N개, 또는 가장 빈번한 N개 값을 찾을 때, row_number() 윈도우 함수 대신 이 방법이 권장됩니다. 

 

5. 필요한 열만 SELECT

열 기반 형식 (parquet, ORC)을 사용할 때, SELECT * 대신 필요한 열만 지정하면 s3에서 읽는 데이터 양도 함께 줄어듭니다. 

결과 열 수가 너무 많으면 ` GENERIC_INTERNAL_ERROR: io.airlift.bytecode.CompilationException ` 오류가 발생할 수 있습니다. 

 

TIP) Athena는 스캔한 데이터 용량만큼 과금됩니다. 열 수를 줄이면 쿼리 속도 뿐만 아니라, 비용도 함께 절감됩니다.

 

 

6. 근사 집계 함수 사용

정확한 값이 필요하지 않은 분석이라면 근사 함수를 사용하여 메모리와 실행 시간을 크게 줄일 수 있습니다. 

COUNT(DISTICT)대신 approx_distinct

 

7. LIKE 대신 regexp_like, 검색 범위 고정

`LIKE '%substring%'`처럼 앞뒤 와일드카드를 모두 사용하면 전체 문자열을 스캔합니다.

접두사 검색이라면 `'substring%'`으로 검색을 고정하거나,` regexp_like(col, '^substring')`을 사용하세요. 

 

regex_like가 like보다 유리한 경우

  • 여러 패턴을` | `(or) 로 한번에 검사
  • like를 세 번 따로 쓰는 것보다 regex_like가 더 빠름
  • 정규 표현식 엔진이 더 빠르게 처리한다. 
  • like 5개짜리 쿼리를 regexp_like 하나로 바꾸면 17% 빨라진다.

 

8. UNION ALL vs UNION

UNION은 중복 제거를 위해 모든 레코드를 처리하기 때문에, 메모리와 컴퓨팅 자원을 많이 소모합니다. 

중복 제거가 꼭 필요한 경우가 아니라면 반드시 UNION ALL을 사용하세요.

 

9. 대용량 결과는 UNLOAD로 내보내기

일반 쿼리 결과는 압축되지 않은 단일 csv로 저장되지만, `UNLOAD`는 워커 노드에서 병렬로 직접 쓰기 때문에 훨씬 빠릅니다. 

parquet, json등 압축 방식으로도 저장할 수 있습니다. 

 

TIP) 결과가 수만행을 초과하거나, 후속 분석을 위해 압축/컬럼형 포맷이 필요할 때 UNLOAD를 선택하세요.

 

10. 자주 쓰는 집계는 CTAS로 구체화

여러 쿼리가 동일한 조인과 집계를 공유한다면, `CREATE TABLE AS SELECT(CTAS)`또는 Glue ETL로 결과를 새 테이블로 사전 계산해둡니다. 대시보드처럼 동일 로직을 반복 실행하는 경우에 특히 효과적입니다. 단, 새 테이블을 주기적으로 최신 상태로 갱신해야 합니다. 

 

CTAS = Create Table As Select

  • CTAS로 공통 부분을 먼저 저장하고, 이후 위젯들은 가벼운 쿼리만 날림
  • 조인 결과를 새 테이블로 저장 -> 이후 쿼리는 이 테이블만 읽음
  • 즉, 자주 쓰는 복잡한 쿼리를 미리 계산해서 테이블로 저장해두는 것.

 

11. 쿼리 결과 재사용 설정

짧은 시간 안에 동일한 쿼리가 여러번 실행될 때 (ex. 여러 사용자가 같은 대시보드 오픈), Athena의 쿼리 결과 재사용 기능을 활성화하면 이전 결과를 반환합니다. TTL을 지정해 refresh를 제어할 수 있습니다. 

 

12. EXPLAIN으로 실행 계획 사전 분석

복잡한 조인 조건은 모든 레코드를 교차 비교시킬 수 있어서, 실행 시간이 레코드 수의 제곱에 비례해 증가합니다. 

쿼리를 실행하기 전에 EXPLAIN문으로 실행 계획을 확인하고 병목을 사전에 파악하면 좋습니다.

 

 

 

https://docs.aws.amazon.com/ko_kr/athena/latest/ug/performance-tuning-query-optimization-techniques.html

 

쿼리 최적화 - Amazon Athena

이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.

docs.aws.amazon.com

 

반응형

'인프라 > AWS' 카테고리의 다른 글

2주안에 AWS SAA + DVA 뽀개기  (0) 2026.03.27
[RDBMS와 NoSQL의 추구미] 돌고 도는 트레이드 오프  (0) 2026.03.24
AWS RDS(MySQL) Migration하기 (📦 새 계정으로 이사가요)  (0) 2025.11.11
Auto Scaling with NLB (Network Load Balancer)  (0) 2025.06.03
'인프라/AWS' 카테고리의 다른 글
  • 2주안에 AWS SAA + DVA 뽀개기
  • [RDBMS와 NoSQL의 추구미] 돌고 도는 트레이드 오프
  • AWS RDS(MySQL) Migration하기 (📦 새 계정으로 이사가요)
  • Auto Scaling with NLB (Network Load Balancer)
kiritoni
kiritoni
안녕하세요, cool & soft한 엔지니어가 되고싶은 토니입니다!
    반응형
  • kiritoni
    Code Art Online
    kiritoni
  • 전체
    오늘
    어제
    • 분류 전체보기 (38)
      • 이야기 (6)
      • 개발 (10)
        • Java (1)
        • Spring (9)
      • 인프라 (17)
        • AWS (5)
        • Server (12)
      • 공부 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    network
    server
    backend
    java
    구름톤딥다이브
    Spring boot
    CS
    웹
    be
    AUSG
    dynamodb
    nlb
    백준
    JPA
    gdgoc
    docker
    kdt
    빅챗
    AWS
    알고리즘
    springboot
    보안
    ubuntu
    Linux
    후기
    서버
    구름톤
    pfsense
    Spring
    springSecurity
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
kiritoni
AWS Athena 쿼리 성능 최적화하기
상단으로

티스토리툴바