Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Apache Iceberg The Definitive Guide 輪読会 - 3章 Li...

Apache Iceberg The Definitive Guide 輪読会 - 3章 Lifecycle of Write and Read Queries

SnowVillage で開催されている Apache Iceberg: The Definitive Guide 輪読会の資料です。

Ryuji Doi

July 23, 2024
Tweet

More Decks by Ryuji Doi

Other Decks in Technology

Transcript

  1. Apache Iceberg: The Definitive Guide 輪読会 Chapter 3. Lifecycle of

    Write and Read Queries 2024/07/22 Ryuji Doi @diosql 1
  2. はじめに ▪ 本資料は「Apache Iceberg: The Definitive Guide」の Chapter 3.を意訳・要約したものです ▪

    発表の内容は個人の見解に基づくものであり、 所属企業を代表するものではありません 2 Chapter 3. Lifecycle of Write and Read Queries
  3. 項目 書籍内の実行環境/サービス 発表者の実行環境/サービス クエリエンジン Spark SQL or Dremio Spark SQL

    ストレージ Amazon S3 Minio (Amazon S3) カタログ Hadoop Catalog JDBC Catalog ▪ Apache IcebergのWrite / Readのクエリのライフサイクルを学ぶ章 ▪ 確認対象の操作 – CREATE TABLE – INSERT – MERGE INTO – SELECT – SELECT [TIMESTAMP|VERSION] AS OF ▪ クエリ実行環境 docker環境があればTabular社のImageで 簡単に構築可能です。 Chapter 3. Lifecycle of Write and Read Queries 4 Chapter 3. Lifecycle of Write and Read Queries GitHub - tabular-io/docker-spark-iceberg
  4. Writing Queries in Apache Iceberg Icebergにおける書き込みプロセスの概要 1. クエリがエンジンに送られ、エンジンは 受け取ったクエリを解析 2.

    エンジンはカタログから最新のMetadata file の場所を取得し、スキーマやパーティショ ン情報を得る 3. Metadata fileに基いてData fileを書き込む 4. Manifest fileを作成 5. Manifest listを作成 6. Metadata fileを作成 7. カタログ上のMetadata fileのポインタを更新 5 Chapter 3. Lifecycle of Write and Read Queries Figure 3-2. Overview of the Apache Iceberg write process
  5. ▪ 4つのカラムを持つordersテーブルを作成 ▪ 第1章で学んだHidden partitioningを使用することで、 カラムを追加することなく時間単位での パーティショニングを可能にしてる おさらい:Hiveでは・・・ Hiveではパーティション列は明示的にテーブルレイアウト に含める必要があったため、パーティション用に粒度を

    荒くした新しいカラムを作る必要があった。 CREATE TABLE orders ( order_id BIGINT, customer_id BIGINT, order_anount DECIMAL(10, 2), order_ts TIMESTAMP, order_date VARCHAR ) PARTITIONED BY order_date Writing Queries in Apache Iceberg # spark SQL CREATE TABLE orders ( order_id BIGINT, customer_id BIGINT, order_amount DECIMAL(10, 2), order_ts TIMESTAMP ) USING iceberg PARTITIONED BY (HOUR(order_ts)) # Dremio CREATE TABLE orders ( order_id BIGINT, customer_id BIGINT, order_amount DECIMAL(10,2), order_ts TIMESTAMP ) PARTITION BY (HOUR(order_ts)) 6 Chapter 3. Lifecycle of Write and Read Queries CREATE TABLE CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  6. Writing Queries in Apache Iceberg 7 Chapter 3. Lifecycle of

    Write and Read Queries CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF 1. クエリがエンジンに送られ、エンジンは受け取ったクエリを解析 2. Metadata fileを書き込む – ファイルシステムに対して下記の内容を含むMetadata fileを作成 ▪ カラムやデータ型などのスキーマ情報 ▪ パーティション仕様 ▪ テーブルの一意な識別子(table-uuid) – この時点ではデータがないためスナップショットに関する情報は含まれない – ファイルシステム上では以下の形で作成される 3. カタログ内のテーブルのメタデータポインタを更新 – Hadoop Catalogの場合はversion-hint.textファイルを更新 S3://datalake/db1/orders/metadata/v1.metadata.json CREATE TABLE
  7. Writing Queries in Apache Iceberg 8 Chapter 3. Lifecycle of

    Write and Read Queries 最終的な状態: CREATE Figure 3-3. Hierarchy of the Iceberg components after executing CREATE CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  8. Writing Queries in Apache Iceberg 9 Chapter 3. Lifecycle of

    Write and Read Queries CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF Appendix:実際に作成されたMetadata file ※ 書籍掲載部分以外を記載 CREATE TABLE 00000-089c823a-6951-4dde-9088-8a583deac2b5.metadata.json { "format-version" : 2, "table-uuid" : "8f3f8be6-378a-466d-bc50-6465ad79530c", "location" : "s3://warehouse/public_schema/orders", "last-sequence-number" : 0, "last-updated-ms" : 1721639106198, "last-column-id" : 4, "current-schema-id" : 0, “schemas" : [ { "type" : "struct", "schema-id" : 0, "fields" : [ { "id" : 1, "name" : "order_id", "required" : false, "type" : "long“ }, { "id" : 2, … "last-partition-id" : 1000, "default-sort-order-id" : 0, "sort-orders" : [ { "order-id" : 0, "fields" : [ ] } ], "properties" : { "owner" : "root", "write.parquet.compression-codec" : "zstd“ }, "current-snapshot-id" : -1, "refs" : { }, "snapshots" : [ ], "statistics" : [ ], "partition-statistics" : [ ], "snapshot-log" : [ ], "metadata-log" : [ ] }
  9. ▪ 作成したテーブルにレコードを挿入するクエリ ▪ パーティションの構造は意識することなく、 直感的にINSERTクエリの実行が可能 Writing Queries in Apache Iceberg

    #Spark SQL/Dremio's SQL Query Engine INSERT INTO orders VALUES ( 123, 456, 36.17, '2023-03-07 08:10:23' ) 10 Chapter 3. Lifecycle of Write and Read Queries INSERT CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  10. 1. クエリがエンジンに送られ、エンジンは 受け取ったクエリを解析 2. エンジンはカタログにリクエストを行い、 最新のMetadata fileの場所を取得し読み込む – エンジンがMetadata fileを読み込む

    目的は、テーブルのスキーマ、パーティ ション仕様を把握し、それらに準拠した Data fileの書き込みを行うため 3. Data fileを書き込む – パーティション仕様に基きレコードを Parquet形式のData fileとして書き込む ▪ Parquetがデフォルトだが変更可能 – テーブルにソート順が定義されている場合 は書き込む前にソートする Writing Queries in Apache Iceberg 11 Chapter 3. Lifecycle of Write and Read Queries INSERT CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF S3://datalake/db1/orders/data/order_ts_hour=2 023-03-07-08/0_0_0.parquet Figure 3-2. Overview of the Apache Iceberg write process
  11. Writing Queries in Apache Iceberg 12 Chapter 3. Lifecycle of

    Write and Read Queries 4. Manifest fileを書き込む – 書き込んだData fileの情報を基に以下の内容が 書き込まれる ▪ Data fileのファイルパス ▪ 列の上下限、Null値のカウント等の統計情報 – これらの情報はpruningのために使用される – Data fileの書き込みプロセスで統計情報を計算 するため、ゼロから計算するより軽量 – Avro形式で書き込まれる INSERT CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF S3://datalake/db1/orders/metadata/6S2ach3d7-e2-4cbc- 8e41-58809fcacb3e.avro Figure 3-2. Overview of the Apache Iceberg write process
  12. Writing Queries in Apache Iceberg 13 Chapter 3. Lifecycle of

    Write and Read Queries 5. Manifest listを書き込む – 以下の内容が書き込まれる ▪ Manifest fileのファイルパス ▪ 追加または削除されたData file/行の数 ▪ パーティション列の上下限などの統計情報 – これらの情報はPruningのために使用される – Data fileの書き込みプロセスで統計情報を計算 するため、ゼロから計算するより軽量 – Avro形式で書き込まれる INSERT CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF S3://datalake/db1/orders/metadata/snap- 8333017788700497002-1-4010cc03-55B5-458c-9Fdc- 188de318c3e6.avro Figure 3-2. Overview of the Apache Iceberg write process
  13. Writing Queries in Apache Iceberg 14 Chapter 3. Lifecycle of

    Write and Read Queries 6. Metadata fileを書き込む – 既存のスナップショット(Manifest list) と、 書き込み結果が反映されたスナップショット (Manifest list)を含む新しいMetadata fileを生成 – 以下の情報が書き込まれる ▪ Manifest listのファイルパス ▪ スナップショットID ▪ 操作の概要 7. 同時実行制御とカタログ内のテーブルのメタデータポ インタを更新 – カタログにアクセスしてINSERT操作中に他の スナップショットがコミットされていないことを 確認(楽観的制御) – 競合がないことを確認したらテーブルの Metadata fileのポインタを更新 – ある場合は再試行する INSERT CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF S3://datalake/db1/orders/metadata/v2.metadata.json Figure 3-2. Overview of the Apache Iceberg write process
  14. Writing Queries in Apache Iceberg 15 Chapter 3. Lifecycle of

    Write and Read Queries 最終的な状態: INSERT CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF Figure 3-4. Iceberg component's hierarchy after executing INSERT
  15. Writing Queries in Apache Iceberg 16 Chapter 3. Lifecycle of

    Write and Read Queries Appendix:実際に作成された各種メタデータ ※ 書き込みで変更が生じた部分を記載 INSERT CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF 00001-c66d7f61-966b-4d5c-88eb-eb27be3fd4b8.metadata.json snap-9006317672960246604-1-3fb5e932-89a8-4562-809b-c57f5cb0185a.avro 3fb5e932-89a8-4562-809b-c57f5cb0185a-m0.avro { "format-version" : 2, "table-uuid" : "8f3f8be6-378a-466d-bc50-6465ad79530c", … "current-snapshot-id" : 9006317672960246604, "refs" : { "main" : { "snapshot-id" : 9006317672960246604, "type" : "branch“ } }, "snapshots" : [ { "sequence-number" : 1, "snapshot-id" : 9006317672960246604, "timestamp-ms" : 1721639116127, "summary" : { "operation" : "append", "spark.app.id" : "local-1721636380786", "added-data-files" : "1", "added-records" : "1", "added-files-size" : "1277", "changed-partition-count" : "1", "total-records" : "1", "total-files-size" : "1277", "total-data-files" : "1", "total-delete-files" : "0", "total-position-deletes" : "0", "total-equality-deletes" : "0“ }, "manifest-list" : "s3://warehouse/public_schema/orders/metadata/snap-9006317672960246604- 1-3fb5e932-89a8-4562-809b-c57f5cb0185a.avro", "schema-id" : 0 } ], "statistics" : [ ], "partition-statistics" : [ ], "snapshot-log" : [ { "timestamp-ms" : 1721639116127, "snapshot-id" : 9006317672960246604 } ], "metadata-log" : [ { "timestamp-ms" : 1721639106198, "metadata-file" : "s3://warehouse/public_schema/orders/metadata/00000-a4e79217-a293-41ac- 9d5d-a1663b957390.metadata.json“ } ] }
  16. ▪ orders, orders_stagingの2つのデータセットを マージ – order_idが一致していればorder_amountを 更新、一致しなければレコード挿入 Writing Queries in

    Apache Iceberg #spark SQL MERGE INTO orders o USING (SELECT * FROM orders_staging) s ON o.order_id = s.order_id WHEN MATCHED THEN UPDATE SET order_amount = s.order_amount WHEN NOT MATCHED THEN INSERT *; #Dremio MERGE INTO orders o USING (SELECT * FROM orders_staging) s ON o.order_id = s.order_id WHEN MATCHED THEN UPDATE SET order_amount = s.order_amount WHEN NOT MATCHED THEN INSERT (order_id, customer_id, order_amount, order_ts) s.order_amount VALUES (s.order_id, s.customer_id, s.order_amount, s.order_ts) 17 Chapter 3. Lifecycle of Write and Read Queries MERGE INTO CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  17. 1. クエリがエンジンに送られ、エンジンは 受け取ったクエリを解析 2. エンジンはカタログにリクエストを行い、 最新のMetadata fileの場所を取得し読み込む – 実行計画策定のため、MERGE元とMERGE先、 両方のテーブルの情報を取得

    – エンジンがMetadata fileを読み込む目的は、 テーブルのスキーマ、パーティション仕様 を把握し、それらに準拠したData fileの 書き込みを行うため Writing Queries in Apache Iceberg Chapter 3. Lifecycle of Write and Read Queries MERGE INTO CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF Figure 3-2. Overview of the Apache Iceberg write process
  18. 3. Data fileを書き込む – エンジンはMERGE元、MERGE先両方の テーブルのデータをメモリにロードし、 一致するレコードを走査 – 一致するレコードの更新はテーブルプロパ ティで定義された戦略に基づいて行われる

    ▪ Copy-On-Write (COW) ▪ Merge-On-Read (MOR) – 本書の例ではデフォルトのCOWが採用され ているため、以下のようにData fileを作成 Writing Queries in Apache Iceberg Chapter 3. Lifecycle of Write and Read Queries MERGE INTO CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF #一致するレコード(更新) S3://datalake/db1/orders/data/order_ts_hour=2023-03-07-08/0_0_1.parquet #一致しないレコード(挿入) S3://datalake/db1/orders/data/order_ts_hour=2023-01-27-10/0_0_0.parquet Figure 3-2. Overview of the Apache Iceberg write process
  19. Writing Queries in Apache Iceberg 20 Chapter 3. Lifecycle of

    Write and Read Queries 4. Manifest fileを書き込む – 書き込んだ2つのData fileの情報を基に以下の 内容が書き込まれる ▪ Data fileのファイルパス ▪ 列の上下限値、Null値のカウント等の統計情報 – これらの情報はpruningのために使用される – Data fileの書き込みプロセスで統計情報を計算 するため、ゼロから計算するより軽量 – Avro形式で書き込まれる MERGE INTO s3://datalake/db1/orders/metadata/faf71ac0-3ace-4910- 9080-c2e688148066.avro Figure 3-2. Overview of the Apache Iceberg write process CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  20. Writing Queries in Apache Iceberg 21 Chapter 3. Lifecycle of

    Write and Read Queries 5. Manifest listを書き込む – 以下の内容が書き込まれる ▪ Manifest fileのファイルパス ▪ 追加または削除されたData file/行の数 ▪ パーティション列の上下限などの統計情報 – これらの情報はPruningのために使用される – Data fileの書き込みプロセスで統計情報を計算 するため、ゼロから計算するより軽量 – Avro形式で書き込まれる MERGE INTO s3://datalake/db1/orders/matadata/snap- 5139476312242609518-1-e22ff753-2738-4d7d.a810- d65dcc1abe63.avro Figure 3-2. Overview of the Apache Iceberg write process CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  21. Writing Queries in Apache Iceberg 22 Chapter 3. Lifecycle of

    Write and Read Queries 6. Metadata fileを書き込む – 既存のスナップショット(Manifest list) と、 書き込み結果が反映されたスナップショット (Manifest list)を含む新しいMetadata fileを生成 – 以下の情報が書き込まれる ▪ Manifest listのファイルパス ▪ スナップショットID ▪ 操作の概要 7. 同時実行制御とカタログ内のテーブルのメタデータ ポインタを更新 – カタログにアクセスしてMERGE操作中に他の スナップショットがコミットされていないことを 確認(楽観的制御) – 競合がないことを確認したらテーブルの Metadata fileのポインタを更新 – ある場合は処理を再試行する MERGE INTO s3://datalake/db1/orders/metadata/v3.metadata.json Figure 3-2. Overview of the Apache Iceberg write process CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  22. Writing Queries in Apache Iceberg 23 Chapter 3. Lifecycle of

    Write and Read Queries 最終的な状態: MERGE INTO Figure 3-5. Iceberg components hierarchy after executing MERGE INTO CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  23. ▪ ordersテーブルの全列を取得するクエリ ▪ ポイントはパーティションカラムorder_tsを 使ってfilter処理を実行している部分 – CREATE TABLEでHOUR(order_ts)という指定 でパーティション仕様を定義したが、この 仕様を意識することなくWHERE句に

    指定することが可能 Reading Queries in Apache Iceberg #Spark SQL/Drenio Sonar SELECT * FROM orders WHERE order_ts BETWEEN '2023-01-01' AND '2023-01-31' 24 Chapter 3. Lifecycle of Write and Read Queries SELECT CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  24. 1. クエリがエンジンに送られ、エンジンは 受け取ったクエリを解析 2. エンジンはカタログにリクエストを行い、 最新のMetadata fileの場所を取得し読み込む – Metadata fileの以下の情報を参照

    ▪ 最新のスナップショットIDの取得 ▪ テーブルのスキーマの把握 Reading Queries in Apache Iceberg Chapter 3. Lifecycle of Write and Read Queries SELECT Figure 3-6. How a READ query works in Apache Iceberg CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  25. 3. Manifest listを読み取り、スナップショットの 以下の情報を取得 ▪ Manifest fileのファイルパス ▪ パーティション 仕様/統計情報

    4. Manifest fileを開き、以下の情報を取得 ▪ Data fileのファイルパス ▪ 各列の上下限値、Null値のカウントなどの 統計情報 – ここで上記で得たパーティション統計情報 とクエリのfilter条件を照合し、一致しない Data fileは無視する 5. 必要なData fileを参照し、レコードをユーザー に返す Reading Queries in Apache Iceberg Chapter 3. Lifecycle of Write and Read Queries SELECT Figure 3-6. How a READ query works in Apache Iceberg CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  26. ▪ ordersテーブルにおける過去の特定の時点の データを参照するTime Travelのクエリ ▪ Icebergにおいて、Time Travelを使用する方法は 2通り – タイムスタンプを使用する

    – スナップショットIDを使用する ▪ タイムスタンプ値を使う場合は、正確に指定し ないとIcebergはエラーを返す Reading Queries in Apache Iceberg ##タイムスタンプ # Spark SQL SELECT * FROM orders TIMESTAMP AS OF '2023-03-07 20:45:08.914' # Dremio SELECT * FROM orders AT TIMESTAMP '2023-03-07 20:45:08.914’ ##スナップショット # Spark SQL SELECT * FROM orders VERSION AS OF 8333017788700497002 # Dremio SELECT * FROM orders AT SNAPSHOT 8333017788700497002 27 Chapter 3. Lifecycle of Write and Read Queries SELECT ~ AS OF CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF IllegalArgunentException: Cannot find a snapshot older than 2023-03-06721:28:35+00:00.
  27. ▪ テーブルのタイムスタンプおよびスナップショットIDは下記のクエリで取得が可能 今回はINESRT実行後のデータを取得する Reading Queries in Apache Iceberg # Spark

    SQL SELECT * FROM catalog.db.orders.history; # Dremio SELECT * FROM TABLE (table_history('orders')) 28 Chapter 3. Lifecycle of Write and Read Queries SELECT ~ AS OF CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF CREATE実行後 INSERT実行後 MERGE INTO実行後
  28. 1. クエリがエンジンに送られ、エンジンは 受け取ったクエリを解析 2. エンジンはカタログにリクエストを行い、 最新のMetadata fileの場所を取得し読み込む – Metadata fileの以下の情報を参照

    ▪ 利用可能なスナップショットのリスト ▪ クエリで指定されたスナップショット ▪ パーティション仕様 – なお、Metadata fileは意図的に期限切れに した場合を除いて、テーブルで生成された すべてのスナップショットを追跡している Reading Queries in Apache Iceberg Chapter 3. Lifecycle of Write and Read Queries SELECT ~ AS OF Figure 3-7. How the time-travel query works in Iceberg CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF s3://datalake/db1/orders/metadata/snap- 8333017788700497002-1-4010cc03-5585-458c-9fdc- 188de318c3e6.avro
  29. 3. Manifest listを読み取り、スナップショットの 以下の情報を取得 ▪ Manifest fileのファイルパス ▪ 追加/削除されたData fileの数

    ▪ パーティション 仕様/統計情報 4. Manifest fileを開き、以下の情報を取得 ▪ Data fileのファイルパス ▪ 列の上下限値、Null値のカウント等の統計 情報 – ここで上記で得たパーティション統計情報 とクエリのfilter条件を照合し、一致しない Data fileは無視する Reading Queries in Apache Iceberg Chapter 3. Lifecycle of Write and Read Queries SELECT ~ AS OF Figure 3-7. How the time-travel query works in Iceberg CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  30. 5. 必要なData fileを参照し、レコードをユーザーに 返す Reading Queries in Apache Iceberg Chapter

    3. Lifecycle of Write and Read Queries SELECT ~ AS OF Figure 3-7. How the time-travel query works in Iceberg CREATE INSERT MERGE INTO SELECT SELECT ~ AS OF
  31. Conclusion ▪ この章では Apache Iceberg における Write / Read 操作のライフサイクルを、

    サンプルクエリ実行を通じて確認した ▪ 4章では Apache Iceberg テーブルへのデータの読み書きの際に、 高パフォーマンスを確保するために利用可能な最適化技術について説明する 32 Chapter 3. Lifecycle of Write and Read Queries