使用 Athena 查詢 Apache Hudi 資料集 - Amazon Athena

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 Athena 查詢 Apache Hudi 資料集

Apache Hudi 是一個開源資料管理架構,可簡化增量資料的處理。記錄級的插入、更新、更新插入和刪除動作會得到更細微的處理,從而減少開銷。Upsert 是指將記錄插入現有資料集 (如果記錄尚不存在),或者更新記錄 (如果記錄存在) 的能力。

Hudi 處理資料插入和更新事件,而不會建立許多可能會導致分析效能問題的小型檔案。Apache Hudi 會自動追蹤變更和合併檔案,以便檔案保持在最佳的大小。如此可避免建置自訂解決方案,這些解決方案用來監控許多小型檔案並將其重新寫入較少的大型檔案。

Hudi 資料集適用於以下使用案例:

會使用開放儲存格式將 Hudi 管理的資料集存放在 Amazon S3 中。目前,Athena 可以讀取經壓縮的 Hudi 資料集,但不能寫入 Hudi 資料。Athena 支援高達 0.8.0 的胡迪版本與 Athena 引擎第 2 版,胡迪版本 0.14.0 與 Athena 引擎版本 3。可能會變動。Athena 無法保證與使用較新版本 Hudi 建立之資料表的讀取相容性。如需有關 Athena 引擎版本控制的資訊,請參閱Athena 引擎版本控制。如需有關 Hudi 功能和版本控制的詳細資訊,請參閱 Apache 網站上的 Hudi 文件

Hudi 資料集資料表類型

Hudi 資料集可以是以下類型之一:

  • 寫入時複製 (CoW) – 資料會以單欄式格式 (Parquet) 存放,每次更新都會在寫入期間建立新版本的檔案。

  • 讀取時合併 (MoR) – 資料的存放是使用單欄式 (Parquet) 和以資料行為基礎 (Avro) 格式的組合。更新會記錄到以資料行為基礎的 delta 檔案,並視需要壓縮以建立新版本的單欄式檔案。

使用 CoW 資料集,每次有記錄進行更新時,包含記錄的檔案就會以更新的值重寫。若使用 MoR 資料集,每次有更新時,Hudi 只會寫入已變更之記錄的資料行。MoR 更適合較少讀取,而寫入或變更較繁重的工作負載。CoW 更適合資料變更較不頻繁,而讀取作業較為繁重的工作負載。

Hudi 提供三個可用於資料存取的查詢類型:

  • 快照查詢 – 查詢會查看截至給定遞交或壓縮動作的資料表的最新快照。對於 MoR 資料表,快照查詢會公開資料表的最新狀態,方法是合併查詢時最新檔案切片的基底和 delta 檔案。

  • 增量查詢 – 查詢只會看到自給定的遞交/壓縮以來在資料表中寫入的新資料。這會有效地提供變更串流,以啟用增量資料管道。

  • 讀取最佳化查詢 – 對於 MoR 資料表,查詢會看到壓縮的最新資料。對於 CoW 資料表,查詢會看到遞交的最新資料。

下表顯示每個資料表類型可能的 Hudi 查詢類型。

資料表類型 可能的 Hudi 查詢類型
寫入時複製 快照、增量
讀取時合併 快照、增量、讀取最佳化

目前,Athena 支援快照查詢和讀取最佳化查詢,但不支援增量查詢。在 MoR 資料表上,所有公開給讀取最佳化查詢的資料均經過壓縮。這可提供良好的效能,但不包含最新的 delta 遞交。快照查詢包含最新資料,但會產生一些運算開銷,這使得這些查詢的效能較為不佳。

如需有關資料表和查詢類型之間取捨的詳細資訊,請參閱 Apache Hudi 文件中的資料表和查詢類型

Hudi 術語變更:檢視現在是查詢

從版本 0.5.1 開始,Apache Hudi 變更了一些術語。以前的檢視在後續版本中稱為查詢。下表摘要列出新舊術語之間的變更。

舊術語 新術語

CoW:讀取最佳化檢視

MoR:即時檢視

快照查詢

增量檢視 增量查詢
MoR 讀取最佳化檢視 讀取最佳化查詢

Bootstrap 操作中的資料表

從 Apache Hudi 版本 0.6.0 開始,引導操作功能可為現有 Parquet 資料集提供更好的效能。引導操作不會重寫資料集,而是只能產生中繼資料,使資料集保持在原位。

您可以使用 Athena,透過引導操作對資料表執行查詢,就像以 Amazon S3 中之資料為基礎的其他資料表一樣。在 CREATE TABLE 陳述式中,請在 LOCATION 子句中指定 Hudi 資料表路徑。

有關在 Amazon 中使用引導操作創建 Hudi 表的更多信息EMR,請參閱 AWS 大數據博客中 Amazon EMR 提供的 Apache Hudi 新功能一文。

Hudi 中繼資料清單

Apache Hudi 有一個中繼資料表,其中包含索引功能,以改善效能,例如檔案列出、使用資料欄統計數字略過資料以及基於 Bloom 篩選條件的索引。

在這些功能中,Athena 目前僅支援檔案列出索引。檔案列出索引可從維護分割區到檔案映射的索引中擷取資訊,進而消除諸如「清單檔案」之類的檔案系統呼叫。這樣就不需要遞迴列出資料表路徑下的每個分割區來查看檔案系統。當您處理大型資料集時,此索引會大幅縮短在寫入和查詢期間取得檔案清單時所產生的延遲。它還可以避免瓶頸,例如 Amazon S3 LIST 呼叫上的請求限制限流。

注意

Athena 目前不支援資料略過或 Bloom 篩選索引。

啟用 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 不支援增量查詢。

  • CTAS— Athena 不支援CTASINSERT INTO不支援 Hudi 資料。如果您希望 Athena 提供寫入 Hudi 資料集的支援,請將意見回饋傳送至

    如需有關寫入 Hudi 資料的詳細資訊,請參閱下列資源:

  • MSCKREPAIRTABLE— 不支援在 Athena 的 Hudi 表MSCKREPAIRTABLE上使用。如果您需要載入未在中建立的 Hudi 表格 AWS Glue,請使用ALTER 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 查詢。

  • 時間戳記查詢 — 目前,嘗試讀取 Hudi 即時資料表中時間戳記資料行的查詢會失敗或產生空白結果。此限制僅適用於讀取時間戳記資料行的查詢。只包含來自相同資料表的非時間戳記資料行的查詢成功。

    失敗的查詢會傳回類似下列內容的訊息:

    GENERICINTERNAL_ERROR: 類別組織. 阿帕奇 .io. ArrayWritable無法轉換為類別組織 .hadoop.hive.serde2.io。 TimestampWritableV2 (組織. 阿帕奇 .io. ArrayWritable 和組織 .apache.hadoop.hive.serde2.io. TimestampWritableV2 是在裝載機 IO.trino.server 的未命名模塊。 PluginClassLoader @75c67992)

其他資源

如需搭配 Athena 搭配使用 Apache Hudi 的其他資源,請參閱下列資源。

影片

下列影片顯示如何使用 Amazon Athena,查詢基於 Amazon S3 的資料湖中已經過讀取最佳化的 Apache Hudi 資料集。

部落格文章

下列 AWS 大數據部落格文章包含如何搭配 Athena 使用 Apache Hudi 的說明。

建立 Hudi 資料表

本節提供 Athena 中 Hudi 資料分區和非分區資料表的CREATETABLE陳述式範例。

如果您已在中建立了 Hudi 資料表 AWS Glue,您可以直接在 Athena 中查詢它們。在 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://DOC-EXAMPLE-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://DOC-EXAMPLE-BUCKET/folder/partition_cow/'

以下 ALTER TABLE ADD PARTITION 範例會將兩個分割區新增至範例 partition_cow 資料表。

ALTER TABLE partition_cow ADD PARTITION (event_type = 'one') LOCATION 's3://DOC-EXAMPLE-BUCKET/folder/partition_cow/one/' PARTITION (event_type = 'two') LOCATION 's3://DOC-EXAMPLE-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://DOC-EXAMPLE-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://DOC-EXAMPLE-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://DOC-EXAMPLE-BUCKET/folder/partition_mor/'

以下 ALTER TABLE ADD PARTITION 範例會將兩個分割區新增至範例 partition_mor 資料表。

ALTER TABLE partition_mor ADD PARTITION (event_type = 'one') LOCATION 's3://DOC-EXAMPLE-BUCKET/folder/partition_mor/one/' PARTITION (event_type = 'two') LOCATION 's3://DOC-EXAMPLE-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://DOC-EXAMPLE-BUCKET/folder/partition_mor/'

同樣地,以下 ALTER TABLE ADD PARTITION 範例會將兩個分割區新增至範例 partition_mor_rt 資料表。

ALTER TABLE partition_mor_rt ADD PARTITION (event_type = 'one') LOCATION 's3://DOC-EXAMPLE-BUCKET/folder/partition_mor/one/' PARTITION (event_type = 'two') LOCATION 's3://DOC-EXAMPLE-BUCKET/folder/partition_mor/two/'

其他資源