AWS athena - Performance Tuning

Sibeet·2022년 9월 26일
0

Athena

목록 보기
1/1

Performance tuning in Athena

대부분 대용량 데이터 기준의 튜닝 포인트로 얘기하는 듯 함.

이것저것 많지만 개인적으로 숙지해야 될 것 위주로 적어 본다.

쓰잘데기 없다 싶은 것도 많은듯…

Data size

Avoid single large files, Read a smaller amount of data at once

‘한 개의 큰 파일’을 자제하고, ‘한번에 작은 양의 파일’을 읽어야 한다.

athena는 다른 DB와 다르게 인덱스가 따로 존재하지 않고 partition key를 통해 인덱싱 하는 것으로 보인다.

partition은 일반적으로 파일을 나눠서 하는 경우가 많기도 하고… file을 직접 읽어 데이터를 추출하는 athena라면 파일 갯수를 병렬로 나누어 주는 것이 연산 상 이점이 충분할 것으로 보이긴 한다.

Avoid having too many columns

너무 많은 컬럼을 읽어오지 말 것. ( SELECT * 와 같은 )

일반 RDBMS또한 대용량을 다룬다면 동일한 튜닝포인트라고 볼 수 있다.

column 수를 줄이는 것이 더 적은 양의 데이터를 가져오고 join할 때도 덜 왔다갔다 한다는 뜻.

Avoid large Query outputs & Avoid scanning an entire table

너무 많은 양의 데이터를 피할 것 & 전체 테이블 스캔을 피할 것

인덱스가 없다 보니 별 갖은 방법을…다 얘기하는 듯 하다. workaround로 CREATE TABLE AS SELECT ~ 구문을 추천하는 듯 함.(CTAS라나 뭐라나)

일반적으로 한 테이블에 많은 양의 데이터를 넣는 것이 부담스러우므로, scan 양을 줄이는 것이 지상 목표인 듯.

  • * 사용을 자제하기.
  • 한 개의 쿼리에서 여러 번의 테이블 스캔을 자제하기
  • filter(WHERE 등) 사용하기
  • LIMIT 애용하기

일반적인 쿼리 사용 주의점과 비슷한 레벨.

If possible, avoid having a large number of small files

가능하다면 ‘너무 많은 양의 작은 파일’을 피할것.

위의 내용과 모순된다 싶어 좀 어이 없었는데 자세히 살펴 보니 그런 내용은 아니고, 아마존 S3와 아테나 모두 ‘초당 5500 리퀘스트’ 제한이 걸려 있다. 이걸 바꿀 수 있는 지는 모르겠으나…

작은 파일 단위로 수백만 개의 object를 쿼리로 조회한다고 했을 때, 이 초당 5500 리퀘스트 제한에 걸리게 되므로… 운이 나쁘다면 백만 개에 200초 정도가 걸릴 수도 있겠다.

If possible이 왜 나왔냐 하니, 일단은 AWS glue라는 서비스가 있긴 해서 이걸 통해 파일을 그룹핑하고 큰 파일처럼 다룰 수 있게 지원하는 것 같다.

https://aws.amazon.com/ko/premiumsupport/knowledge-center/glue-job-output-large-files/

https://docs.aws.amazon.com/glue/latest/dg/grouping-input-files.html

ETL도 있고 이것저것…

File formats

Use an efficient file format such as parquet or ORC

parquet이나 ORC 파일 사용하기.

parquet와 같은 column base 파일 포맷이 유리하다는 것

ORC : https://cwiki.apache.org/confluence/display/hive/languagemanual+orc

parquet : https://github.com/apache/parquet-format

대용량 데이터를 다룰 때 column-base의 이점은 상당히 크기 때문에 성능 차이가 꽤 날 것으로 생각되긴 한다.

Switch between ORC and parquet formats

parquet ↔  ORC 변경해보기

같은 데이터라도 해당 두 포맷이 큰 차이를 보일 수도 있다고 한다.

parquet는 압축에 강점을 보이니 중복성이 짙은 데이터는 효율성이 좋을 것이고, ORC는 일반 columnar의 특징을 가지고 있으니 해당 상황에 맞춰 사용하면 좋을 수 있겠다.

**Joins, grouping, and unions**

Reduce the usage of memory intensive operations

메모리를 많이 사용하는 쿼리 피하기

JOIN, GROUP BY, ORDER BY, UNION과 같은 쿼리들은 메모리에 많은 양의 데이터를 올려놓게 될 수도 있다.

aggregation 쿼리들은 다른 벤더에서도 많은 코스트를 유발하므로 아테나도 마찬가지인 듯

Consider using UNION ALL

UNION ALL을 사용하기

UNION은 중복 제거 로직이 있고, UNION ALL은 중복 제거 로직이 없다.

당연히 중복 제거 로직이 없는 UNION ALL이 빠르다. 어차피 where절 등으로 원하는 row만 뽑기 때문에 일반적으로 UNION ALL을 사용하게 돼 있음.

Partitioning

Limit the number of partitions in a table

파티션의 갯수에 제한을 두기

10만 개 이상 파티션이 존재할 경우 AWS에 과도한 리퀘스트를 날려 느려질 수 있다…

5500개의 제한 또한 문제가 될 수 있을 듯 한데, 정확하게 그렇게 적어놓진 않은 듯.

  • ALTER TABLE DROP PARTITION으로 필요 없는 파티션 제거
  • 제거하기 힘든 상황에는 partition projection 사용

참고 : https://docs.aws.amazon.com/athena/latest/ug/partition-projection.html

partition projection이 뭔가 하니, 기존에는 파티션 정보를 가져올 때 GetPartitions API를 사용하는데 이게 상당한 부하를 유발할 수 있다고 한다. before pruning이라 하는 것을 보니, 인덱스 파편화 등의 문제로 부하가 걸릴 수 있는듯.

RDBMS에서 특정 컬럼만 가져오는 것 처럼, 파티션 또한 그렇게 작동할 수 있다~

To add new partitions frequently, use ALTER TABLE ADD PARTITION

ALTER TABLE ADD PARTITION을 사용할 것

파일을 추가하고 파티션을 추가하는 방법엔 두 가지가 있는데, 그 중 하나 얘기다.

  • MSCK REPAIR TABLE : 모든 파티션을 조회하고 추가, 삭제 작업 수행
  • ALTER TABLE ADD PARTITION : 해당 파티션만 지정하여 테이블에 추가

적어 놓은 것으로도 알 수 있듯 전자는 모든 하위 디렉토리를 훑기 때문에 엄청난 시간이 걸릴 수 있다.

MSCK는 처음 테이블 생성 시 누락을 방지하기 위해 수행 해 주되, 주기적으로 데이터가 추가되는 파이프라이닝 상황에서는 ADD PARTITION을 애용한다.

Avoid using coalesce() in a WHERE clause with partitioned columns

WHERE절에 coalesce()를 사용하지 말 것

명확한 이유를 적어 놓진 않았으나… 굳이 coalesce에 한정되지 않고 function 대부분을 얘기하고 있긴 하다.

일반적으로 WHERE절에 함수가 들어갈 경우 성능 저하를 일으킬 수 있다. RDBMS index에서도 동일한 문제이고 아테나는 더할 수도 있겠다. 이럴 경우 workaround 쿼리(가능하다면)로 부하를 줄여 주는 것이 좋다.

기타

Minimize the use of window functions

window function을 최소하하기

rank와 같은 윈도우 함수들은 많은 메모리 사용을 유발한다. 집계 함수 대부분이 그런 식이기도 하나, 파티션에 대부분의 코스트를 의존하고 있는 아테나에겐 더 치명적일 수 있다.

엄청난 빅데이터 셋을 조회하게 될 경우 장애를 일으킬 수 있다.

  • 윈도우 함수를 사용할 때 filter 적용
  • partition by를 통해 특정 파티션만 적용
  • workaround 쿼리 사용(말은 쉽다 ㅋㅋ…)

Use more efficient functions

좀 더 효율적인 함수 트릭 사용

여기에 좀 꿀팁이 있는 듯…

row_number() OVER (…) as rnk … WHERE rnk = 1 대신 LIMIT

row_number를 이용한 rank 집계 함수 같은 느낌인데, 이것을 Group by , order by, limit 1 등을 이용해서 메모리에 올라가는 양을 줄이라는 것으로 보인다.

보통 RDBMS에서는 limit를 걸 경우 데이터셋을 딱 원하는 만큼만 fetch하기 때문에 상당한 속도 차이가 있는데, 이게 아테나에서도 적용되는진 의문이다. (실제로 아닌 경우도 있고)

어쨌거나 LIMIT를 권장할 정도면 속도 차이는 분명 있겠지. partition당 1 set만 가져온다거나..

LIKE 구문 대신 정규 표현식

LIKE ‘%string%’ 은 인덱싱이 제대로 존재하지 않는 아테나에선 치명적일 것이다.

b-tree index로 트리를 나눠 놓은 것도 아니고..필연적으로 거대한 데이터셋 스캔을 동반할 듯.

regexp_like() 함수가 있다고 하니 이걸 이용해서 하라고 한다.

참고 : https://prestodb.io/docs/current/functions/regexp.html#regexp_like

그 외에도 있으나 생략.

추가 문서 :

Top 10 Performance Tuning Tips for Amazon Athena | Amazon Web Services

이거 외에도 뭔가 팁이 있는 듯 한데, 다음에 정리할 게 있으면 또 하고…

0개의 댓글