AWS 기술 블로그

Amazon EMR에서 Trino와 S3 Select Pushdown을 사용해 쿼리 성능 개선

이 글은 AWS Storage Blog에 게시된 Run queries up to 9x faster using Trino with Amazon S3 Select on Amazon EMR by Boni Bruno and Eric Henderson 글을 기반으로, 아래의 내용을 추가로 다룹니다.

  • CloudFormation을 활용해, 실습을 위한 Amazon EMR 클러스터와 S3 버킷의 테스트 데이터 구성
  • Trino의 쿼리 환경에서 S3 Select Pushdown 기능을 On & Off 하면서 워크로드 비교

이 게시글에서는 Amazon EMR의 쿼리 엔진인 Trino 환경에서 S3 Select Pushdown을 활용하는 방법을 알아봅니다. 실습 과정에서 독자들은 S3 Select Pushdown 기능 활용에 따른 워크로드 변화를 이해할 수 있습니다.

Trino와 S3 Select를 함께 사용하기

오늘날 많은 기업 고객들은 데이터 레이크를 구축함으로써 데이터 저장 및 접근방식을 혁신하고 있습니다. 데이터 레이크 환경에는 다양한 종류의 데이터가 대규모로 저장되므로, 데이터를 효과적으로 필터링하여 원하는 데이터를 빠르게 검색하기 위해 오픈소스 프레임워크를 활용하는 등 다양한 데이터 접근 방법을 시도합니다. 최종적으로 데이터 접근 성능이 개선되면, 데이터 분석가는 더 많은 시간과 노력을 데이터 분석과 인사이트 발굴에 할애할 수 있게 됩니다.

Amazon S3 Select는 간단한 SQL 문을 사용해 Amazon Simple Storage Service(Amazon S3)에 저장된 객체의 콘텐츠를 필터링하고, 객체로부터 필요한 데이터 서브셋만 검색하는 기능입니다. S3 Select를 사용해 데이터를 필터링하면, S3로부터 전송되는 데이터 양이 줄어들면서 데이터 검색에 드는 비용과 지연 시간이 감소합니다.

Trino는 Amazon S3에 저장된 데이터의 대화형 분석에 활용할 수 있는 오픈소스 SQL 쿼리 엔진입니다. 2022년 11월 21일, AWS는 CSV 및 JSON 데이터에 접근할 때 쿼리 성능을 향상시키는, 오픈소스 Trino에 대한 업스트림 기여(Upstream contributions)를 발표했습니다. Trino 쿼리 엔진에서 지원하는 S3 Select Pushdown 기능은 쿼리의 프로젝션(예: SELECT) 및 조건자 연산(예: WHERE)에 필요한 계산 작업을 Amazon S3에 “Pushdown”하는 기능입니다. S3 Select Pushdown 기능을 활용하면, 워크로드에 따라 Trino에서 처리해야 할 데이터 양이 줄어들면서 일부 데이터 처리 애플리케이션의 성능이 향상됩니다.

Trino로 Amazon S3 데이터에 쿼리하는 워크로드에서, 다음 특징을 고려해 S3 Select Pushdown 기능을 활용합니다.

  1. Trino 쿼리로 원본 데이터의 절반 이상이 필터링 되는 경우에 적합합니다.
  2. CSV, JSON 형식으로 저장된 객체를 대상으로 활용하기 좋습니다.
  3. Parquet 등 컬럼 형식 객체에는 사용할 수 없습니다.

실습

아키텍처 소개

Trino는 다양한 데이터베이스에 대한 ANSI SQL 쿼리를 지원하는 오픈소스 SQL 쿼리 엔진입니다. 실습에서 CloudFormation으로 구성되는 EMR 클러스터에는 Trino 및 Apache Hive가 애플리케이션으로 실행되며, 실습을 위한 테스트 데이터는 S3 버킷에 위치합니다. 이후, 실습 준비단계에서 Hive Metastore를 통해 S3 버킷의 데이터의 위치 및 스키마가 정의됩니다. 준비가 완료되면 Trino 설정에서 S3 Select Pushdown 기능을 On & Off 하면서 쿼리를 수행하고, 데이터 처리량과 쿼리 수행시간을 비교합니다.

단계1 : 사전준비

본 실습에서는 CloudFormation을 통해 Amazon EMR 클러스터 및 S3 버킷의 벤치마크 데이터셋을 사전 생성합니다. 다음 버튼을 눌러 CloudFormation 스택 배포 화면으로 이동합니다.

사전 설정된 파라미터를 그대로 유지한 상태로, IAM 자원을 생성하는 권한을 CloudFormation에 부여하고 스택을 생성합니다.

단계2 : 클러스터 연결

  1. CloudFormation 스택 생성이 완료되면, Outputs 탭에서 키 ‘MainNodeConsoleConnectLink’에 해당하는 URL을 클릭합니다.
    그러면 Amazon EMR 클러스터 메인 노드의 EC2 인스턴스 콘솔로 이동합니다.
  2. 콘솔에서 인스턴스를 선택해 ‘Connect’ 버튼을 누른 다음, Session Manager로 세션을 연결합니다.

  3. 연결된 세션에서 아래 명령어를 입력해, hadoop 유저로 전환합니다.
    sudo su - hadoop

단계3 : Hive 테이블 생성

  1. 홈 디렉토리에는 여러 스크립트가 사전 정의되어 있습니다.
    아래 명령어를 터미널에 입력하여, create-tables.sql에 정의된 SQL 구문을 Hive CLI로 수행합니다.
    쿼리가 완료되면, 테스트 데이터가 저장된 S3 버킷(trino-workshop-data-*)을 대상으로 하는 스키마가 생성됩니다.

    hive -f create-tables.sql
  2. Trino는 클러스터 상호작용을 위한 CLI를 제공합니다. 아래 명령어를 통해 Trino CLI를 호출하면서 카탈로그로 hive, 스키마로 workshop을 지정합니다. 그러면 Trino의 대화형 쿼리 세션에 연결됩니다.
    trino-cli --catalog hive --schema workshop
  3. Trino 쿼리 세션에서 아래 명령어를 통해 workshop 스키마의 모든 테이블을 조회합니다.
    show tables;

    위 단계까지 정상적으로 수행 되었다면 아래와 같은 테이블 목록이 출력됩니다. 이제 Trino는 Hive MetaStore를 통해 S3의 CSV 데이터에 접근할 준비가 됐습니다.

    trino:workshop> show tables;
    Table
    ------------------------
    call_center
    catalog_page
    catalog_returns
    catalog_sales
    customer
    ...
    web_page
    web_returns
    web_sales
    web_site
    (24 rows)
    
    Query 20230125_170209_00003_iev8q, FINISHED, 4 nodes
    Splits: 29 total, 29 done (100.00%)
    0.22 [24 rows, 688B] [109 rows/s, 3.05KB/s]

단계4-1 : S3 Select Pushdown 활용하지 않고 Trino 쿼리 수행

S3 Select Pushdown 기능은 Trino의 기본 구성에서 비활성화 되어 있습니다. 먼저, 비활성화 상태에서 몇 가지 쿼리를 수행할 예정입니다.

  1. S3 Select Pushdown의 비활성화를 확실히 하기 위해, 아래 명령을 수행합니다.
    set SESSION hive.s3_select_pushdown_enabled=false;
  2. 데이터의 정상 접근을 확인하기 위해, item 테이블의 컬럼 목록과 데이터 유형을 조회합니다.
    DESCRIBE items;

    item 테이블에 얼마나 많은 아이템들이 있는지 개수를 확인합니다.

    SELECT count(*) as items FROM item;
  3. 아래 명령어를 복사 및 붙여넣기 하여, 조건자가 포함된 복잡한 쿼리를 실행합니다. 참고로, 아래 쿼리는 ‘설정된 조건에 부합하는 상점 별, 요일 별 매출의 총합’을 계산합니다.
    select s_store_name, s_store_id,
    sum(case when (d_day_name='Sunday') then ss_sales_price else null end) sun_sales,
    sum(case when (d_day_name='Monday') then ss_sales_price else null end) mon_sales,
    sum(case when (d_day_name='Tuesday') then ss_sales_price else null end) tue_sales,
    sum(case when (d_day_name='Wednesday') then ss_sales_price else null end) wed_sales,
    sum(case when (d_day_name='Thursday') then ss_sales_price else null end) thu_sales,
    sum(case when (d_day_name='Friday') then ss_sales_price else null end) fri_sales,
    sum(case when (d_day_name='Saturday') then ss_sales_price else null end) sat_sales
    from date_dim, store_sales, store
    where d_date_sk = ss_sold_date_sk and
    s_store_sk = ss_store_sk and
    s_gmt_offset = -5 and
    d_year = 1998
    group by s_store_name, s_store_id
    order by s_store_name, s_store_id,sun_sales,mon_sales,tue_sales,wed_sales,thu_sales,fri_sales,sat_sales
    limit 100;

    쿼리 수행결과는 아래와 같이 출력됩니다. (데이터 처리량 380 MB, 쿼리 수행시간 5.40초)

    s_store_name |    s_store_id    | sun_sales | mon_sales | tue_sales | wed_sales | thu_sales | fri_sales | sat_sales
    --------------+------------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------
     able         | AAAAAAAACAAAAAAA | 459564.35 | 492832.21 | 472234.89 | 513998.92 | 480718.61 | 480887.30 | 482390.93
     ation        | AAAAAAAAHAAAAAAA | 468604.40 | 467302.10 | 470821.49 | 510779.71 | 481377.21 | 473673.49 | 471487.62
     bar          | AAAAAAAAKAAAAAAA | 495341.98 | 461667.28 | 476791.38 | 498368.24 | 475762.43 | 476690.98 | 462227.22
     eing         | AAAAAAAAIAAAAAAA | 487998.32 | 460740.37 | 486454.06 | 447624.87 | 468239.16 | 468815.86 | 502495.16
     ese          | AAAAAAAAEAAAAAAA | 466373.15 | 477718.02 | 486363.59 | 490049.12 | 483203.25 | 470427.77 | 497738.02
     ought        | AAAAAAAABAAAAAAA | 442199.17 | 483945.97 | 497270.79 | 483466.92 | 496373.09 | 491362.25 | 462524.87
    (6 rows)
    
    Query 20230125_171719_00006_742sw, FINISHED, 3 nodes
    Splits: 263 total, 263 done (100.00%)
    5.40 [2.95M rows, 380MB] [547K rows/s, 70.5MB/s]
    

단계4-2 : S3 Select Pushdown 활용해 Trino 쿼리 수행

  1. 이번에는 아래 명령으로 S3 Select Pushdown 기능을 활성화 합니다.
    set SESSION hive.s3_select_pushdown_enabled=true;
  2. 앞에 수행한 것과 동일한 분석 쿼리를 수행합니다. 참고로, CloudFormation 배포 과정에서 Caching 비활성화가 미리 설정되어 있기 때문에, 앞의 쿼리 수행이 후속 쿼리 성능에 영향을 주지 않습니다. s3_select_pushdown_enabled 설정에 따라, Trino에서 S3 Select Pushdown을 자동으로 처리합니다.
    select s_store_name, s_store_id,
    sum(case when (d_day_name='Sunday') then ss_sales_price else null end) sun_sales,
    sum(case when (d_day_name='Monday') then ss_sales_price else null end) mon_sales,
    sum(case when (d_day_name='Tuesday') then ss_sales_price else null end) tue_sales,
    sum(case when (d_day_name='Wednesday') then ss_sales_price else null end) wed_sales,
    sum(case when (d_day_name='Thursday') then ss_sales_price else null end) thu_sales,
    sum(case when (d_day_name='Friday') then ss_sales_price else null end) fri_sales,
    sum(case when (d_day_name='Saturday') then ss_sales_price else null end) sat_sales
    from date_dim, store_sales, store
    where d_date_sk = ss_sold_date_sk and
    s_store_sk = ss_store_sk and
    s_gmt_offset = -5 and
    d_year = 1998
    group by s_store_name, s_store_id
    order by s_store_name, s_store_id,sun_sales,mon_sales,tue_sales,wed_sales,thu_sales,fri_sales,sat_sales
    limit 100;

    쿼리 수행결과를 확인합니다. (데이터 처리량 42.3 MB, 쿼리 수행시간 3.90초)

    s_store_name |    s_store_id    | sun_sales | mon_sales | tue_sales | wed_sales | thu_sales | fri_sales | sat_sales
    --------------+------------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------
     able         | AAAAAAAACAAAAAAA | 459564.35 | 492832.21 | 472234.89 | 513998.92 | 480718.61 | 480887.30 | 482390.93
     ation        | AAAAAAAAHAAAAAAA | 468604.40 | 467302.10 | 470821.49 | 510779.71 | 481377.21 | 473673.49 | 471487.62
     bar          | AAAAAAAAKAAAAAAA | 495341.98 | 461667.28 | 476791.38 | 498368.24 | 475762.43 | 476690.98 | 462227.22
     eing         | AAAAAAAAIAAAAAAA | 487998.32 | 460740.37 | 486454.06 | 447624.87 | 468239.16 | 468815.86 | 502495.16
     ese          | AAAAAAAAEAAAAAAA | 466373.15 | 477718.02 | 486363.59 | 490049.12 | 483203.25 | 470427.77 | 497738.02
     ought        | AAAAAAAABAAAAAAA | 442199.17 | 483945.97 | 497270.79 | 483466.92 | 496373.09 | 491362.25 | 462524.87
    (6 rows)
    
    Query 20230125_172747_00010_742sw, FINISHED, 3 nodes
    Splits: 263 total, 263 done (100.00%)
    3.90 [2.88M rows, 42.3MB] [739K rows/s, 10.9MB/s]
    

    S3 Select Pushdown 기능을 활성화 함에 따라, Trino 쿼리에서 직접 처리한 데이터가 380 MB -> 42.3 MB로 약 89% 감소했고, 쿼리 수행시간은 5.4초 -> 3.9초로 약 28% 개선됐습니다.

단계5 : S3 Select Pushdown을 활용해 TPC-DS 분석 쿼리 수행

실습에서 활용하고 있는 TPC-DS 데이터셋은 의사결정 지원 시스템의 쿼리 및 데이터 관리를 모델링하는 벤치마크  도구입니다. 이 실습에서는 scale = 1 (약 1GB)의 소규모 데이터 샘플을 활용하며, 대용량 성능 벤치마크보다는 기능 데모에 가깝습니다. 이번 단계에는 데이터 샘플에 대해 네 가지의 TPC-DS 쿼리(22, 34, 41, 73)를 수행하면서 워크로드를 검증할 예정입니다. 대상 SQL  쿼리 문서는 ~/local-queries/ 경로에 저장되어 있으므로, 문서를 통해 각 쿼리에 대한 세부사항을 확인할 수 있습니다.

이 단계에서는 사전에 준비한 run-workshop-tpcds.sh 스크립트를 활용해, 4개 쿼리를 수행하고 그 결과를 CSV로 저장합니다. 스크립트를 호출할 때 사용하는 -w 플래그는 S3 Select Pushdown 기능의 사용 여부를 전달합니다.

  1. 아래 명령을 통해, S3 Select Pushdown 기능을 비활성화 상태에서 TPC-DS-like 쿼리를 수행합니다.
    ./run-workshop-tpcds.sh \
    -t workshop \
    -w n

    이 스크립트에서는 쿼리를 5번 수행하고 결과를 CSV 파일로 기록합니다. 스크립트 수행이 완료되면 5개의 결과 파일이 result_trino_without_select_*.csv 라는 이름으로 저장됩니다. 각 파일은 아래와 같은 CSV 형식으로 4개 쿼리의 수행시간을 저장합니다.

    query, execution_time(second), start_time, end_time
    query22.sql, 2.20, 18:33:41, 18:33:44
    query34.sql, 2.59, 18:33:44, 18:33:47
    query41.sql, 0.60, 18:33:47, 18:33:49
    query73.sql, 1.53, 18:33:49, 18:33:51
  2. 이번에는 S3 Select Pushdown 기능을 활성화한 상태로 스크립트를 수행합니다.
    ./run-workshop-tpcds.sh \
    -t workshop \
    -w y

    같은 형식의 결과가 result_trino_with_select_*.csv 에 저장됩니다.

  3. 아래 스크립트를 수행하면, 자동으로 결과 그래프를 그려서 S3 버킷에 업로드합니다.
    ./plot-and-upload-results.sh

    스크립트가 실행된 후 터미널에 출력되는 URL을 클릭하면, 객체가 저장된 S3 콘솔 화면으로 이동합니다.
    콘솔 우측 상단의 ‘Open’ 버튼을 클릭하여, 결과 그래프를 확인합니다.

  4. 그래프의 y축에는 4개 쿼리를 5번 실행했을 때의 평균 수행시간(초)이 표시되며, 이 값이 낮을 수록 성능이 우수함을 의미합니다. 아래 그림을 보면, 본 실험 환경에서 4개의 TPC-DS 쿼리와 S3 Select Pushdown 기능을 함께 사용하여 쿼리 수행시간이 개선됐습니다. (성능 개선 효과는 쿼리 워크로드 및 실험조건에 따라 달라질 수 있습니다.)

리소스 정리하기

실습이 완료되면, 향후 불필요한 과금을 예방하기 위해 실습에 사용했던 리소스를 모두 제거합니다.

  1. CloudFormation 스택 : Amazon EMR 클러스터
  2. 데이터 소스를 위한 S3 버킷 : trino-workshop-data-*

결론

S3에 저장된 빅데이터를 대상으로 Trino (Release 397~) 쿼리엔진을 사용하고 있다면, 프로젝션 작업과 조건자 연산을 Amazon S3에 “Pushdown” 함으로써 쿼리 성능을 향상시킬 수 있습니다. 이 글에서는 소규모의 실험 환경(약 1 GB 데이터셋, 3개 노드 클러스터, 4개 분석 쿼리)을 활용해서 S3 Select Pushdown 기능의 데모를 진행했습니다. 원문으로 작성된 블로그 글에서는 대규모 실험환경(약 3 TB 데이터셋, 33개 노드 클러스터, 99개 분석 쿼리)에서 벤치마크를 수행했고, 해당 조건에서 최대 9배(평균 2.5배)의 쿼리 수행 시간 개선, 21배의 데이터 처리량 감소를 확인한 바 있습니다.

보다 자세한 내용은 Trino의 Release Note에 소개되어 있습니다. S3 Select Pushdown 기능은 Trino Hive connector에서 기본으로 비활성화(disabled) 상태입니다. Trino 쿼리에 의해 필터링 되는 레코드(rows)가 많다면 S3 Select Pushdown 사용을 고려하되, 애플리케이션의 워크로드마다 성능에 미치는 영향이 다르므로, 프로덕션 도입에 앞서 Trino 속성 값을 변경하며 벤치마크 해볼 것을 권장합니다. S3 Select에 대한 과금 모델은 다음 링크의 Management & Analytics 탭의 S3 Select 비용 항목을 참고해 주십시오.

Kihyeon Myung

Kihyeon Myung

명기현 솔루션즈 아키텍트는 다양한 분야의 엔지니어 경험을 바탕으로, 고객이 AWS 클라우드에서 효율적 아키텍처를 구성하고, 원하는 비즈니스 목표를 달성할 수 있도록 지원하고 있습니다.