订阅更新

Iceberg Manifest 和元数据裁剪是怎么工作的?

面试问 182 约 2 分钟读完

本文目录
  1. 面试怎么回答
  2. Snapshot 是查询的一致元数据入口
  3. Manifest List 先过滤清单文件
  4. Manifest 再过滤 Data File
  5. 为什么 Manifest 也需要维护
  6. 一个典型场景
  7. 参考资料

面试怎么回答

Iceberg 查询先从 Snapshot 获取 Manifest List,利用其中的分区范围过滤不相关 Manifest;再读取命中的 Manifest,用每个 Data File 的分区值和列级上下界、空值数等统计继续裁剪,最后才生成数据扫描任务。它避免全目录枚举,但小 Manifest、统计失真和文件布局不匹配仍会拖慢规划,需要分别做 Rewrite Manifests 与数据文件 Compaction。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

一张表有几十万个数据文件,查询规划却不需要把整个目录列一遍。

Iceberg 能做到这一点,靠的不是更快的文件系统,而是一棵可裁剪的元数据树。

Iceberg 用 Manifest List 和 Manifest 的多级统计信息,把查询谓词逐层下推到元数据,在真正读取数据前排除无关文件。


Snapshot 是查询的一致元数据入口

每次提交产生新的 Snapshot,Snapshot 指向本次表状态对应的 Manifest List。查询先固定一个 Snapshot,再沿元数据引用查找文件,因此规划看到的是一致版本,不需要依赖对象存储目录列表猜测表状态。

Manifest List 先过滤清单文件

Manifest List 保存该 Snapshot 引用的 Manifest,以及每个分区字段的范围等摘要。查询谓词转换为分区条件后,可以先排除完全不可能命中的 Manifest,避免打开全部清单文件。

Manifest 再过滤 Data File

Manifest 记录各数据文件的路径、分区值、记录数以及列级 lower bound、upper bound、null count 等统计。规划器用这些信息排除不可能满足条件的数据文件,剩余文件才生成 Scan Task。它判断的是文件是否可能命中,不是替代数据行级过滤。

Iceberg 的多级元数据裁剪路径

为什么 Manifest 也需要维护

持续小批写入会积累大量小 Manifest,写入顺序与查询过滤维度不一致时,同一个时间范围可能散落在很多 Manifest 中。Iceberg 可以重写 Manifest 重新分组元数据;数据文件小文件问题则要用 Rewrite Data Files,二者不要混为一谈。

Manifest 重写和数据文件合并不是一件事

一个典型场景

表按 day(event_time) 隐藏分区,但多个任务并发补写不同日期,Manifest 里的日期范围高度交叉。查询一天数据时仍要读取许多 Manifest。通过 Rewrite Manifests 按首个分区字段重新组织后,元数据裁剪更集中;如果每个数据文件本身仍很小,还需要单独做数据文件 Compaction。

参考资料

刷题进度保存在当前浏览器