[reinvent 2024] AWS에서 Apache Iceberg 비용과 성능 튜닝

Summary

데이터 볼륨이 계속 증가하고 실시간 처리가 요구되는 상황에서 Apache Iceberg의 성능을 최적화하면서 비용을 관리하는 것은 어려울 수 있습니다. 이번 세션에서는 Iceberg의 작동 방식, 구성 방법, 고급 성능 최적화 옵션, 그리고 다양한 워크로드 패턴에 맞게 Iceberg를 조정하는 방법에 대해 다룹니다. 페타바이트 규모의 배치 작업이든 실시간 스트리밍 수집이든 관계없이, 일반적인 문제와 성능 병목현상, 비용을 관리하면서 Iceberg의 성능을 극대화하기 위한 모범 사례를 배울 수 있습니다.

리인벤트 2024 테크 블로그의 더 많은 글이 보고 싶다면?

Tech Blog

AWS re:Invent 2024 Tech Blog written by MegazoneCloud

Overview

  • Title: Apache Iceberg on AWS: Tuning for cost and performance [REPEAT]
  • Date: 2024년 12월 4일(수)
  • Venue: Mandalay Bay
  • Speaker:
  • Shana Schipers(Specialist SA, Amazon Web Services)
  • Francisco Morillo(Sr. Streaming Solutions Architect, Amazon Web Services)
  • Stefano Sandona(Big Data Specialist Solutions Architect, Amazon Web Services)
  • Carlos Rodrigues(Big Data SA, AWS)
  • Industry: –

들어가며

이번 칼럼에서 다룰 세션은 Iceberg테이블의 성능과 비용 튜닝에 관련한 내용인데요, 해당 세션은 workshop세션으로 최적화된 테이블과 비최적화 테이블을 직접 쿼리해보면서 성능을 비교해보는 식으로 진행됩니다.

Workshop 진행 전에 먼저 Iceberg table 에 대해 먼저 설명드리겠습니다.

Apache Iceberg는 증분 데이터 처리 및 데이터 파이프라인 개발을 간소화하는 오픈 소스 테이블 포맷입니다. 테이블 관리, 효율적인 upsert 및 삭제, 고급 메타데이터를 통한 테이블 접근 개선, 스트리밍 수집 기능, 데이터 및 파일 레이아웃 최적화, 동시성 제어와 같은 기능을 제공하며, Apache Parquet와 Apache Avro와 같은 오픈 소스 파일 포맷에서 데이터를 유지합니다.이어서 workshop을 통해 Iceberg의 주요 작업을 살펴보겠습니다.

Workshop

해당 workshop은 EMR studio workspace에서 진행됩니다.

Workshop에서 사용할 데이터셋입니다. 여기서 ws_order_number 컬럼을 주로 이용해서 워크샵을 진행합니다.

Spark 환경 config를 설정한 다음 Iceberg 카탈로그를 구성하고 Database를 생성합니다. 이 시점부터는 전체 카탈로그가 Iceberg로 설정됩니다.이어서 바로 Iceberg 테이블을 만들 때 읽기 및 쓰기 성능을 최적화하기 위한 여러 가지 구성에 대해 설명드리겠습니다.

Hidden partitioning

먼저 Unoptimized 테이블을 생성합니다. 이 테이블은 Iceberg의 히든 파티셔닝(hidden partitioning) 기능을 활용해 자동으로 파티셔닝되는데요.

Hive에서 파티셔닝된 테이블을 생성할 때는 일반적으로 연도와 월 같은 특정 열을 기준으로 명시적으로 설정해야 하며, 이를 위해 테이블 내에 해당 열을 포함해야 합니다. 하지만 Iceberg에서는 이러한 명시적 파티셔닝 없이, 테이블 열에서 자동으로 파티션을 추론할 수 있습니다.

이 예제에서는 we_sales_time 컬럼을 사용해서 파티셔닝 합니다. 해당 칼럼은 타임스탬프 형식으로, 데이터를 작성하거나 삽입할 때 we_sales_time의 월을 기준으로 파티션이 자동 생성됩니다. 즉, 별도의 설정 없이도 Iceberg가 데이터를 삽입할 때 필요한 파티션을 스스로 설정해 관리합니다.

Optimized 테이블을 생성할 때에도 마찬가지로 파티셔닝을 자동으로 추론하여 생성합니다.

최적화된 테이블에서는 write.metadata.metrics.max-inferred-column-defaults 설정을 19로 지정하여, 테이블의 첫 19개 열에 대한 통계를 수집하도록 설정합니다.

Iceberg에서는 기본적으로 테이블의 첫 100개 열에 대해 통계를 수집하지만, 이 설정을 통해 성능을 최적화하고, 데이터에 대한 효율적인 쿼리 처리가 가능해집니다.

Iceberg는 메타데이터 파일 내에서 각 열에 대한 통계를 수집하는데  예를 들어, Parquet 파일을 포함한 각 데이터 파일을 쓸 때마다 Iceberg는 해당 파일의 열에 대해 통계를 수집합니다.

이를 통해 각 열에 대해 최소값과 최대값을 기록하여, 나중에 쿼리 최적화 및 데이터 검색을 보다 효율적으로 처리할 수 있도록 돕습니다.

Global sort

Iceberg는 데이터를 처리할 때 열 통계(ex. 최소값 및 최대값)를 수집하여, 쿼리 시 불필요한 데이터 파일을 제거하는 프루닝(pruning)을 수행합니다. 자주 조회되는 열인 ws_order_number와 같은 열을 기준으로 데이터를 정렬하면 이러한 프루닝 작업이 더 효과적으로 이루어집니다. 이로 인해 더 많은 파일을 건너뛰게 되어, 쿼리 성능과 쓰기 성능 모두 향상될 수 있습니다.

전역 정렬(Global sort)을 사용하면 ws_order_number와 같은 열을 기준으로 데이터를 정렬함으로써, Iceberg는 쿼리 범위와 일치하지 않는 파일들을 빠르게 제외할 수 있습니다. 또한, 데이터가 기본 키 열을 기준으로 정렬되면, 쓰기 성능이 최적화됩니다. 특히 업데이트 시에는 기본 키 열에서 파일의 겹침이 줄어들어, 하루 동안의 기록이 적은 수의 테이블 파일에만 저장되기 때문에 업데이트 작업이 훨씬 효율적으로 처리됩니다.

정렬 방식에는 로컬 정렬과 전역 정렬두 가지가 있습니다. 로컬 정렬은 데이터가 Spark 파티션 내에서만 정렬되는 방식인 반면, 전역 정렬은 전체 테이블에 걸쳐 데이터를 정렬하여, 더욱 효과적인 파일 프루닝을 수행할 수 있습니다.

Iceberg는 데이터를 Spark Task로 분산하여 저장하기 전에, 데이터 분배 방식을 정의하는 여러 write distribution modes를 제공합니다. 이를 통해 데이터 저장 성능을 최적화하고, 읽기 및 처리 효율성을 개선할 수 있습니다.

그 중 Hash 방식은 데이터를 특정 컬럼이나 컬럼 조합을 기준으로 해싱하여 분배하는 방식입니다. 이 방식에서는 동일한 해시 값을 가진 데이터가 같은 Spark 태스크로 전달되고, 이 데이터는 같은 파티션 파일에 기록됩니다.

예를들어 삽입되는 데이터는 9월과 10월에 해당하며, 각 레코드에는 ws_order_number가 포함됩니다.

데이터 파티셔닝

데이터는 9월과 10월로 파티셔닝됩니다. 작업은 다음과 같이 나뉩니다.

  • 첫 번째 작업은 9월에 해당하는 레코드를 처리합니다.
  • 두 번째 작업은 10월에 해당하는 레코드를 처리합니다.

셔플링

데이터가 각 작업에 의해 읽힌 후, 셔플링 과정이 발생합니다. 셔플링은 데이터를 재분배하여 레코드가 파티션별로 그룹화되도록 합니다. 이 과정은 데이터를 효율적으로 분배하고, 각 작업이 필요한 데이터만 처리하도록 도와줍니다.

데이터 쓰기

셔플링이 끝난 후, 각 작업은 자신에게 할당된 파일을 씁니다

  • 첫 번째 작업은 9월에 해당하는 데이터를 파일에 씁니다.
  • 두 번째 작업은 10월에 해당하는 데이터를 파일에 씁니다.

이 과정에서 타임스탬프의 월 필드에 대한 해시 함수를 사용하여 데이터를 각 작업에 효율적으로 분배합니다. 이를 통해 각 작업이 데이터를 처리하고 분배하는 데 있어 효율성을 보장할 수 있습니다.

Range 방식은 데이터를 파티션 컬럼의 값 범위로 분배하는 방식입니다. 이 방법은 지정된 컬럼의 값 범위를 계산하여, 각 범위에 해당하는 데이터를 Spark 태스크에 분산시킵니다. 이를 통해 데이터가 값 범위에 따라 적절히 분배되며, 각 Spark 태스크는 해당 범위에 속하는 데이터만 처리하게 됩니다.

File size Management

데이터 세트에 파일이 많을수록 데이터를 처리하기 위해 수행해야 하는 작업이 많아집니다. 예를 들어, 각각 100kb인 1000개 파일의 데이터 세트가 있는 경우 1000개 파일 열어야 합니다. 대신 이 데이터 세트를 각각 10MB인 10개 파일로 재구성하면 10개 파일만 열면 됩니다 . 동일한 내용이 Iceberg 데이터 세트에도 적용됩니다. 많은 수의 작은 파일보다 적은 수의 큰 파일이 더 나은 성능을 제공합니다.

Check statistics

Iceberg 테이블은 .files, .manifest, .snapshots 등의 다양한 메타데이터 테이블을 포함하고 이러한 메타데이터 테이블은 테이블 구조와 통계에 대한 상세 정보를 제공합니다. 개별 파일에 대한 통계가 수집되며, 열의 상한값과 하한값 같은 정보가 포함됩니다. 위에 생성한 두 개의 테이블을 비교해보겠습니다.

최적화된 테이블 vs 비최적화된 테이블

  • 최적화된 테이블: 일부 열(ex. 19개)에 대해서만 통계를 수집하여 메타데이터 크기가 작아짐.
  • 비최적화된 테이블: 모든 열에 대한 통계를 수집하여 메타데이터 크기가 크게 증가

Iceberg 테이블에서 관련 열만 통계를 수집하여 메타데이터를 최적화하면 스토리지 효율성과 쿼리 성능을 개선할 수 있으며, 대규모 데이터 처리 환경에서 비용 절감에 큰 도움이 됩니다.

Read performance

특정 ID 조회 시 성능을 비교한 결과, 최적화된 테이블은 쿼리 수행 시간이 약 1초로 빠릅니다. 이는 파일 통계를 활용해 불필요한 데이터를 건너뛰고, 단일 데이터 파일만 메모리에 로드하여 결과를 계산하기 때문입니다. 반면, 비최적화된 테이블은 쿼리 수행 시간이 약 3~4초로 더 오래 걸립니다. 이는 통계 정보가 없어서 여러 데이터 파일을 메모리에 로드하고 처리해야 하므로 성능이 저하되기 때문입니다.

결론

이번 워크샵 세션에서는 Iceberg 테이블의 성능 튜닝 방법에 대해 배우며, 특히 hidden partitioning과 distribution mode를 활용하는 방법에 대해 아이디어를 얻을 수 있었습니다.

샘플 데이터를 통해 실습을 진행하면서 partitioning과 distribution mode를 어떻게 설정하느냐에 따라 데이터 처리 성능이 크게 개선된다는 점을 체감할 수 있었습니다.  이러한 기법을 실데이터에 적용해 본다면 성능 향상 효과를 더욱 뚜렷하게 실현할 수 있을 것 같아 기대가 되었고 얼른 실데이터에 적용해보고 싶다는 생각이 드는 유익한 세션이었습니다.

글 │메가존클라우드, Cloud Technology Center(CTC), Cloud Data SA 팀, 이민정 SA
게시물 주소가 복사되었습니다.