一、概述

Iceberg 数据表每一次的修改后的状态都会在 Metadata Layer 层中生成一个 Snapshot (s0,s1) 文件,Snapshot 文件中包含一个 Manifest List, List 中存储了当前的 Snapshot 状态是由哪些 Manifest 文件组成。每个 Manifest 的文件会指向到真实数据的存储文件 Date File(一股是 parquet 格式)。

二、架构设计

Iceberg 文件布局元数据层中,每一个快照 Snapshot 读取所需要的数据文件都已经清晰的定义在了 manifest list 和 manifest的文件中,并且manifest 文件中还存储了相关的统计信息。

三、元数据文件 metadata.json

查询 Iceberg 表数据时,首先获取最新的 metadata 信息(metadata.json 文件) 这里先获取到 00000-*ec504.metadata.json 元数据信息,解析当前 metadata.json 可以拿到当前表的快照 id:"949358624197301886 以及这张表的所有快照信息

metadata.json 中 snapshots 数组对应的值。

四、表快照 Snapshot

快照代表一张表在某个时刻的状态,一个 Manifest List 文件代表一个快照。

五、清单列表 Manifest List

5.1. 设计

Iceberg 将某个版本或快照的清单文件存贮在清单文件列表中,即 Manifest List 中。Manifest List 文件以 avro 的格式进行存储,每一条记录表示一个 Manifest,其最主要的字段为: manifest_path,通过该字段可以标记清单文件的存储位置。
从 Manifest List 中读取 Manifest File 文件时,Iceberg 会将查询的分区谓词与每个分区字段的值范围进行比较,然后跳过那些没有任何范围重叠的 Manifest File。

使用元数据中的 min-max 索引也会使 Iceberg 会过滤大部分 Manifest File

5.2. 实现

六、Manifest File

6.1. 设计

在 Iceberg 中对于每个数据文件,都会存在一个 Manifest File 来追踪这个数据文件的位置,Manifest File 同时记录了每个 DataFile 的详细描述,包括文件的状态、文件路径、分区信息,列级别的统计信息(比如每列的最大量小值、空值数等)、文件的大小以及文件里面数据的行数等信息。
Manifest File 中统计信息可以在 Scan 的时候为算子下推提供数据,通过检查每个 DataFile 是否与给定的查询过滤器匹配实现 File skip,避免读取不必要的 DataFile.
如下图所示,每个 Manifest File 可追踪多个 DataFile,减少了元数据小文件的生成,同时可以允许跳过整个清单文件以及其关联的数据文件。

6.2. 实现

Iceberg 中 Manifest 文件根据数据文件的类型分为2种,分别是数据类型(都是新增数据)和删除类型(都是删除数据文件)

1
2
3
4
public enum ManifestContent{
DATA(O),
DELETES (1);
}

Manifest 会记录每个数据文件的状态,包括现存、新增、删除三种:

1
2
3
4
5
6
7
interface ManifestEntry<F extends ContentFile<F>>{
enum Status{
EXISTING(O),
ADDED(1),
DELETED(2);
}
}