iceberg數據讀取流程


 

 

假設我們的表是存儲在 Hive 的 MetaStore 里面的,表名為 iteblog,並且數據的組織結構如上如所示。

1.查詢最新快照的數據

•通過數據庫名和表名,從 Hive 的 MetaStore 里面拿到表的信息。從表的屬性里面其實可以拿到 metadata_location 屬性,通過這個屬性可以拿到 iteblog 表的 Iceberg 的 metadata 相關路徑,這個也就是上圖步驟①的 /user/iteblog/metadata/2.metadata.json。

•解析 /user/iteblog/metadata/2.metadata.json 文件,里面可以拿到當前表的快照 id(current-snapshot-id),以及這張表的所有快照信息,也就是 JOSN 信息里面的 snapshots 數組對應的值。從上圖可以看出,當前表有兩個快照,id 分別為 1 和 2。快照 1 對應的清單列表文件為 /user/iteblog/metastore/snap-1.avro;快照 2 對應的清單列表文件為 /user/iteblog/metastore/snap-2.avro。 

•如果我們想讀取表的最新快照數據,從 current-snapshot-id 可知,當前最新快照的 ID 等於 2,所以我們只需要解析 /user/iteblog/metastore/snap-2.avro 清單列表文件即可。從上圖可以看出,snap-2.avro 這個清單列表文件里面有兩個清單文件,分別為 /user/iteblog/metadata/3.avro 和 /user/iteblog/metadata/2.avro。注意,除了清單文件的路徑信息,還有 added_data_files_count、existing_data_files_count 以及 deleted_data_files_count 三個屬性。Iceberg 其實是根據 deleted_data_files_count 大於 0 來判斷對應的清單文件里面是不是被刪除的數據。由於上圖 /user/iteblog/metadata/2.avro 清單文件的 deleted_data_files_count 大於 0 ,所以讀數據的時候就無需讀這個清單文件里面對應的數據文件。在這個場景下,讀取最新快照數據只需要看下 /user/iteblog/metadata/3.avro 清單文件里面對應的數據文件即可。 

•這時候 Iceberg 會解析 /user/iteblog/metadata/3.avro 清單文件,里面其實就只有一行數據,也就是 /user/iteblog/data/4.parquet,所以我們讀 iteblog 最新的數據其實只需要讀 /user/iteblog/data/4.parquet 數據文件就可以了。注意,上面 /user/iteblog/data/2.avro 文件里面對應的內容為

{"status":2,"data_file":{"file_path":"/user/iteblog/data/3.parquet"}}{"status":2,"data_file":{"file_path":"/user/iteblog/data/2.parquet"}}{“status":2,"data_file":{"file_path":"/user/iteblog/data/1.parquet"}}

其中的 status = 2 代表 DELETED,也就是刪除,也印證了讀最新快照的數據其實不用讀 /user/iteblog/data/2.avro 清單文件的數據文件。而 /user/iteblog/data/3.avro 清單文件里面存儲的內容為 {"status":1,"data_file":{"file_path":"/user/iteblog/data/4.parquet"}},其 status = 1,代表 ADDED,也就是新增的文件,所以得讀取。

2.查詢某個快照的數據

Apache Iceberg 支持查詢歷史上任何時刻的快照,在查詢的時候只需要指定 snapshot-id 屬性即可,比如我們想查詢上面 snapshot-id 為 1 的數據,可以在 Spark 中這么寫:

spark.read .option("snapshot-id", 1L) .format("iceberg") .load("path/to/table") 下面是讀取指定快照的圖示:

 

 

從上圖可以看出,和讀取最新快照數據不一樣的地方是上圖中的第三步。由於我們指定了 snapshot-id = 1,所以 Iceberg 會讀取上面第二步白色的部分,可以知道,snapshot-id = 1 對應的清單列表文件為 /user/iteblog/metastore/snap-1.avro。這時候讀出清單列表里面的文件,其實就只有一行數據,對應的清單文件為 /user/iteblog/metadata/1.avro,其中 added_data_files_count 為 3。

下一步我們讀取 /user/iteblog/metadata/1.avro 清單文件,可以看到里面有三個數據文件路徑,這些數據文件就是 snapshot-id = 1 的數據。

3.根據時間戳查看某個快照的數據

Iceberg 還支持通過 as-of-timestamp 參數指定時間戳來讀取某個快照的數據。如下所示:

spark.read.option("as-of-timestamp","12346").format("iceberg").load("path/to/table")

 

 

我們注意上面圖中第二步里面的 JSON 數據里面有個 snapshot-log 數組,如下:

"snapshot-log":[{"timestamp-ms":12345,"snapshot-id":1},{"timestamp-ms":23456,"snapshot-id":2}]

每個列表里面都有個 timestamp-ms 屬性和 snapshot-id 屬性,並且是按照 timestamp-ms 升序的。在 Iceberg 內部實現中,它會將 as-of-timestamp 指定的時間和 snapshot-log 數組里面每個元素的 timestamp-ms 進行比較,找出最后一個滿足 timestamp-ms <= as-of-timestamp 對應的 snapshot-id。

由於 as-of-timestamp=12346 比 12345 時間戳大,但是比 23456 小,所以會取 snapshot-id = 1,也就是拿到 snapshot-id = 1 的快照數據。剩下的數據查詢步驟和在查詢中指定 snapshot-id 是一致的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM