Athena를 사용하여 Apache Hudi 데이터 집합 쿼리 - Amazon Athena

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

Athena를 사용하여 Apache Hudi 데이터 집합 쿼리

Apache Hudi는 증분 데이터 처리를 간소화하는 오픈 소스 데이터 관리 프레임워크입니다. 레코드 수준의 삽입, 업데이트, 업서트, 삭제 작업이 훨씬 세밀하게 처리되므로 오버헤드가 줄어듭니다. Upsert는 레코드가 존재하지 않으면 기존 데이터 집합에 레코드를 삽입하고 레코드가 존재하면 레코드를 업데이트할 수 있는 기능입니다.

Hudi는 분석 시 성능 문제를 일으킬 수 있는 다수의 작은 파일을 발생시키지 않고도 데이터 삽입 및 업데이트 이벤트를 처리합니다. Apache Hudi는 자동으로 변경 사항을 추적하고 파일을 병합하여 최적의 크기를 유지합니다. 이렇게 하면 다수의 작은 파일을 더 적은 수의 대용량 파일에 다시 쓰고 모니터링하는 사용자 지정 솔루션을 빌드할 필요가 없습니다.

Hudi 데이터 집합은 다음과 같은 사용 사례에 적합합니다.

Hudi가 관리하는 데이터 세트는 오픈 스토리지 형식을 사용하여 Amazon S3에 저장됩니다. 현재 Athena는 압축된 Hudi 데이터 집합을 읽을 수 있지만 Hudi 데이터를 쓸 수는 없습니다. Athena는 Athena 엔진 버전 2의 경우 최대 Hudi 버전 0.8.0을 지원하고 Athena 엔진 버전 3에서는 Hudi 버전 0.14.0까지 지원합니다. 변경될 수 있습니다. Athena는 이후 버전의 Hudi로 생성된 테이블과의 읽기 호환성을 보장할 수 없습니다. Athena 엔진 버전 관리에 대한 자세한 내용은 Athena 엔진 버전 관리 단원을 참조하세요. Hudi 기능 및 버전 관리에 대한 자세한 내용은 Apache 웹 사이트의 Hudi 설명서를 참조하세요.

Hudi 데이터 집합 테이블 유형

Hudi 데이터 집합은 다음 유형 중 하나일 수 있습니다.

  • 쓸 때 복사(CoW) - 데이터가 열 기반 형식(Parquet)으로 저장되며, 각 업데이트마다 쓰기 중에 새 버전의 파일을 만듭니다.

  • 읽을 때 병합(MoR) - 데이터가 열 기반 형식(Parquet)과 행 기반(Avro) 형식을 조합하여 저장됩니다. 업데이트는 행 기반 delta 파일에 기록되며 새 버전의 열 형식 파일을 작성할 때 필요에 따라 압축됩니다.

CoW 데이터 세트를 사용하면 레코드에 대한 업데이트가 있을 때마다 레코드가 포함된 파일이 업데이트된 값으로 다시 작성됩니다. MoR 데이터 세트를 사용하면 Hudi는 업데이트가 있을 때마다 변경된 레코드에 대한 행만 씁니다. MoR은 읽기 수행이 적고 쓰기 또는 변경이 많은 워크로드에 더 적합합니다. CoW는 자주 변경되지 않는 데이터에서 읽기 수행이 많은 워크로드에 더 적합합니다.

Hudi는 데이터 액세스를 위해 세 가지 쿼리 유형을 제공합니다.

  • 스냅샷 쿼리 - 지정된 커밋 또는 압축 작업 시 테이블의 최신 스냅샷을 보는 쿼리입니다. MoR 테이블의 경우 스냅샷 쿼리는 쿼리 시의 최신 파일 슬라이스의 기본 파일과 델타 파일을 병합하여 테이블의 최신 상태를 나타냅니다.

  • 증분의 쿼리 - 이 쿼리는 지정된 커밋/압축 이후 테이블에 기록된 새 데이터만 볼 수 있습니다. 이는 변경 스트림을 효과적으로 제공하여 증분 데이터 파이프라인을 사용할 수 있도록 합니다.

  • 읽기 최적화 쿼리 - MoR 테이블의 경우 쿼리가 압축된 최신 데이터를 표시합니다. CoW 테이블의 경우 이 쿼리는 커밋된 최신 데이터를 보여줍니다.

다음 표에는 각 테이블 유형에 사용할 수 있는 Hudi 쿼리 유형이 나와 있습니다.

테이블 유형 가능한 Hudi 쿼리 유형
쓸 때 복사 스냅샷, 증분
읽을 때 병합 스냅샷, 증분, 읽기 최적화

현재 Athena는 스냅샷 쿼리와 읽기 최적화 쿼리를 지원하지만 증분 쿼리는 지원하지 않습니다. MOR 테이블에서 읽기 최적화 쿼리에 노출된 모든 데이터는 압축됩니다. 이는 우수한 성능을 제공하지만 최근의 델타 커밋은 포함하지 않습니다. 스냅샷 쿼리에는 가장 최신의 데이터가 포함되지만 일정한 계산 오버헤드가 발생하여 이러한 쿼리의 성능이 떨어집니다.

테이블 유형과 쿼리 유형 간의 장단점에 대한 자세한 내용은 Apache Hudi 설명서의 Table & Query Types(테이블 및 쿼리 유형)를 참조하세요.

Hudi 용어 변경: 뷰가 이제 쿼리로 변경됨

릴리스 버전 0.5.1부터 Apache Hudi는 용어의 일부를 변경했습니다. 이전에는 뷰라고 불렀던 것을 후속 릴리스에서는 쿼리라고 부릅니다. 다음 표에 이전 용어와 새 용어 간의 변경 내용이 요약되어 있습니다.

이전 용어 새 용어

CoW: 읽기 최적화 뷰

MoR: 실시간 뷰

스냅샷 쿼리

증분 뷰 증분 쿼리
MoR 읽기 최적화 뷰 읽기 최적화 쿼리

부트스트랩 작업의 테이블

Apache Hudi 버전 0.6.0부터 부트스트랩 작업 기능은 기존의 Parquet 데이터 집합에 향상된 성능을 제공합니다. 부트스트랩 작업은 데이터 집합을 다시 작성하는 대신 데이터 집합을 그대로 두고 메타데이터만 생성할 수 있습니다.

Athena를 사용하면 Amazon S3의 데이터를 기반으로 하는 다른 테이블과 마찬가지로 부트스트랩 작업에서 테이블을 쿼리할 수 있습니다. CREATE TABLE 문에서 LOCATION 절에 Hudi 테이블 경로를 지정합니다.

Amazon EMR에서 부트스트랩 작업을 사용하여 Hudi 테이블을 생성하는 방법에 대한 자세한 내용은 빅 데이터 블로그의 Amazon EMR에서 사용할 수 있는 Apache Hudi의 새로운 기능 문서를 참조하십시오. AWS

Hudi 메타데이터 목록

Apache Hudi에는 파일 목록, 열 통계를 사용한 데이터 건너뛰기, 블룸 필터 기반 인덱스와 같은 성능 향상을 위한 인덱싱 기능이 포함된 메타데이터 테이블이 있습니다.

Athena는 현재 이러한 기능 중 파일 목록 인덱스만 지원합니다. 파일 목록 인덱스는 파일 매핑에 대한 파티션을 유지 관리하는 인덱스에서 정보를 가져와 '파일 나열'과 같은 파일 시스템 호출을 제거합니다. 이렇게 하면 파일 시스템을 보기 위해 테이블 경로 아래에 있는 모든 파티션을 재귀적으로 나열할 필요가 없습니다. 대규모 데이터 세트에 대한 작업을 수행하는 경우 이 인덱싱 기능을 사용하면 쓰기 및 쿼리 중에 파일 목록을 가져올 때 발생할 수 있는 지연 시간이 크게 줄어듭니다. 또한 Amazon S3 LIST 호출에서 요청 한도 제한과 같은 병목 현상을 방지합니다.

참고

Athena는 현재 데이터 건너뛰기 또는 블룸 필터 인덱싱을 지원하지 않습니다.

Hudi 메타데이터 테이블 활성화

메타데이터 테이블 기반 파일 목록은 기본적으로 비활성화되어 있습니다. Hudi 메타데이터 테이블 및 관련 파일 목록 기능을 활성화하려면 hudi.metadata-listing-enabled 테이블 속성을 TRUE로 설정합니다.

다음 ALTER TABLE SET TBLPROPERTIES 예제에서는 예제 partition_cow 테이블의 메타데이터 테이블을 활성화합니다.

ALTER TABLE partition_cow SET TBLPROPERTIES('hudi.metadata-listing-enabled'='TRUE')

고려 사항 및 제한

  • Athena는 증분 쿼리를 지원하지 않습니다.

  • Athena는 Hudi 데이터에 대해 CTAS 또는 INSERT INTO을(를) 지원하지 않습니다. Athena가 Hudi 데이터 집합 쓰기를 지원하길 원하시면 에 피드백을 보내세요.

    Hudi 데이터 쓰기에 대한 자세한 내용은 다음 리소스를 참조하세요.

  • Athena에서는 Hudi 테이블에 MSCK REPAIR TABLE을 사용할 수 없습니다. 에서 생성하지 않은 Hudi 테이블을 로드해야 하는 경우 를 사용하십시오. AWS GlueALTER TABLE ADD PARTITION

  • S3 Glacier 객체 건너뛰기 미지원 – Apache Hudi 테이블의 객체가 Amazon S3 Glacier 스토리지 클래스에 있는 경우 read_restored_glacier_objects 테이블 속성을 false로 설정해도 효과가 없습니다.

    예를 들어 다음과 같은 명령을 실행한다고 가정하겠습니다.

    ALTER TABLE table_name SET TBLPROPERTIES ('read_restored_glacier_objects' = 'false')

    Iceberg 및 Delta Lake 테이블의 경우 이 명령은 지원되지 않는 테이블 속성 키: read_restored_glacier_objects 오류를 생성합니다. Hudi 테이블의 경우 ALTER TABLE 명령은 오류를 생성하지 않지만 여전히 Amazon S3 Glacier 객체를 건너뛰지 않습니다. ALTER TABLE 명령 후에 SELECT 쿼리를 실행하면 계속해서 모든 개체가 반환됩니다.

비디오

다음 동영상은 Amazon Athena를 사용하여 Amazon S3 기반 데이터 레이크에서 읽기에 최적화된 Apache Hudi 데이터 집합을 쿼리하는 방법을 보여 줍니다.

Hudi 테이블 생성

이 단원에서는 Hudi 데이터의 분할된 테이블과 분할되지 않은 테이블에 대한 Athena의 CREATE TABLE 문의 예제를 제공합니다.

에서 이미 Hudi 테이블을 만든 경우 Athena에서 AWS Glue직접 쿼리할 수 있습니다. Athena에서 분할된 Hudi 테이블을 만들 때 ALTER TABLE ADD PARTITION을 실행하여 Hudi 데이터를 로드해야 쿼리가 가능합니다.

쓸 때 복사(CoW) 테이블 생성 예제

분할되지 않은 CoW 테이블

다음 예제에서는 Athena에서 분할되지 않은 CoW 테이블을 만듭니다.

CREATE EXTERNAL TABLE `non_partition_cow`( `_hoodie_commit_time` string, `_hoodie_commit_seqno` string, `_hoodie_record_key` string, `_hoodie_partition_path` string, `_hoodie_file_name` string, `event_id` string, `event_time` string, `event_name` string, `event_guests` int, `event_type` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.HoodieParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://bucket/folder/non_partition_cow/'

분할된 CoW 테이블

다음 예제에서는 Athena에서 분할된 CoW 테이블을 만듭니다.

CREATE EXTERNAL TABLE `partition_cow`( `_hoodie_commit_time` string, `_hoodie_commit_seqno` string, `_hoodie_record_key` string, `_hoodie_partition_path` string, `_hoodie_file_name` string, `event_id` string, `event_time` string, `event_name` string, `event_guests` int) PARTITIONED BY ( `event_type` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.HoodieParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://bucket/folder/partition_cow/'

다음 ALTER TABLE ADD PARTITION 예제에서는 partition_cow 테이블 예제에 2개의 파티션을 추가합니다.

ALTER TABLE partition_cow ADD PARTITION (event_type = 'one') LOCATION 's3://bucket/folder/partition_cow/one/' PARTITION (event_type = 'two') LOCATION 's3://bucket/folder/partition_cow/two/'

읽을 때 병합(MoR) 테이블 생성 예제

Hudi는 MoR용 메타스토어에 두 개의 테이블을 만듭니다. 하나는 스냅샷 쿼리를 위한 테이블이고 하나는 읽기 최적화 쿼리를 위한 테이블입니다. 두 테이블 모두 쿼리가 가능합니다. 0.5.1 이전의 Hudi 버전에서는 읽기 최적화 쿼리용 테이블이 해당 테이블을 만들 때 지정한 이름을 갖습니다. Hudi 버전 0.5.1부터는 기본적으로 테이블 이름에 접미사 _ro가 붙습니다. 스냅샷 쿼리용 테이블의 이름은 지정한 이름에 _rt가 덧붙습니다.

분할되지 않은 읽을 때 병합(MoR) 테이블

다음 예제에서는 Athena에서 읽기 최적화 쿼리를 위한 분할되지 않은 MoR 테이블을 만듭니다. 읽기 최적화 쿼리는 HoodieParquetInputFormat 입력 형식을 사용합니다.

CREATE EXTERNAL TABLE `nonpartition_mor`( `_hoodie_commit_time` string, `_hoodie_commit_seqno` string, `_hoodie_record_key` string, `_hoodie_partition_path` string, `_hoodie_file_name` string, `event_id` string, `event_time` string, `event_name` string, `event_guests` int, `event_type` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.HoodieParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://bucket/folder/nonpartition_mor/'

다음 예제에서는 Athena에서 스냅샷 쿼리를 위한 분할되지 않은 MoR 테이블을 만듭니다. 스냅샷 쿼리의 경우 HoodieParquetRealtimeInputFormat 입력 형식을 사용합니다.

CREATE EXTERNAL TABLE `nonpartition_mor_rt`( `_hoodie_commit_time` string, `_hoodie_commit_seqno` string, `_hoodie_record_key` string, `_hoodie_partition_path` string, `_hoodie_file_name` string, `event_id` string, `event_time` string, `event_name` string, `event_guests` int, `event_type` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.realtime.HoodieParquetRealtimeInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://bucket/folder/nonpartition_mor/'

분할된 읽을 때 병합(MoR) 테이블

다음 예제에서는 Athena에서 읽기 최적화 쿼리를 위한 분할된 MoR 테이블을 만듭니다.

CREATE EXTERNAL TABLE `partition_mor`( `_hoodie_commit_time` string, `_hoodie_commit_seqno` string, `_hoodie_record_key` string, `_hoodie_partition_path` string, `_hoodie_file_name` string, `event_id` string, `event_time` string, `event_name` string, `event_guests` int) PARTITIONED BY ( `event_type` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.HoodieParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://bucket/folder/partition_mor/'

다음 ALTER TABLE ADD PARTITION 예제에서는 partition_mor 테이블 예제에 2개의 파티션을 추가합니다.

ALTER TABLE partition_mor ADD PARTITION (event_type = 'one') LOCATION 's3://bucket/folder/partition_mor/one/' PARTITION (event_type = 'two') LOCATION 's3://bucket/folder/partition_mor/two/'

다음 예제에서는 Athena에서 스냅샷 쿼리를 위한 분할된 MoR 테이블을 만듭니다.

CREATE EXTERNAL TABLE `partition_mor_rt`( `_hoodie_commit_time` string, `_hoodie_commit_seqno` string, `_hoodie_record_key` string, `_hoodie_partition_path` string, `_hoodie_file_name` string, `event_id` string, `event_time` string, `event_name` string, `event_guests` int) PARTITIONED BY ( `event_type` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hudi.hadoop.realtime.HoodieParquetRealtimeInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 's3://bucket/folder/partition_mor/'

마찬가지로 다음 ALTER TABLE ADD PARTITION 예제에서는 partition_mor_rt 테이블 예제에 2개의 파티션을 추가합니다.

ALTER TABLE partition_mor_rt ADD PARTITION (event_type = 'one') LOCATION 's3://bucket/folder/partition_mor/one/' PARTITION (event_type = 'two') LOCATION 's3://bucket/folder/partition_mor/two/'

다음 사항도 참조하십시오.