【数据湖与开放表格式】Lakehouse 全景:从 Hive 表到开放表格式
Hive 目录式分区表把『表』等同于『一组目录加 metastore 里的分区行』,于是没有原子提交、planning 要 LIST 目录、schema 与分区演进常要重写。本文用这三个硬伤切入,讲清 lakehouse 把表拆成『不可变数据文件 + 可变元数据指针 + catalog』三层后各自解决了什么,并给出全系列的分层地图。
发布来自土法炼钢兴趣小组的知识、笔记、进展和应用。主题包括数据结构和算法、编程语言、网络安全、密码学等。
共 7 篇文章 · 返回首页
Hive 目录式分区表把『表』等同于『一组目录加 metastore 里的分区行』,于是没有原子提交、planning 要 LIST 目录、schema 与分区演进常要重写。本文用这三个硬伤切入,讲清 lakehouse 把表拆成『不可变数据文件 + 可变元数据指针 + catalog』三层后各自解决了什么,并给出全系列的分层地图。
目录式分区表(Hive 表)在对象存储上有三处硬伤:并发写部分提交、list planning 太贵、缺快照隔离与原子提交。本文拆开放表格式补上的四件事——原子提交、快照隔离、文件级统计裁剪、schema 与分区演进,并抽象出三家共有的『元数据指针 + 不可变数据文件』骨架。
拆解 Iceberg 的四层元数据:catalog 指针 → metadata.json → manifest list(snapshot)→ manifest file → data file。讲清 snapshot 与 manifest 里的分区数据和列级 stats(lower/upper bound、null/value count)如何让一次查询不 list 目录就收敛到文件集合,并给出表规范 V1/V2/V3 的版本边界。基于 pyiceberg 0.11.1 真实建表逐层 dump。
拆解 Iceberg 的 partition spec 与 transform(identity/bucket[N]/truncate[W]/year/month/day/hour/void):隐藏分区如何让查询不写分区列谓词也能裁剪,分区演进为何不重写历史数据(文件携带所属 spec),以及与 Hive 静/动态分区的本质差异。基于 pyiceberg 0.11.1 真实演进 spec 并观察新旧文件。
Iceberg 在不可变文件上做行级删除的两条路线:copy-on-write(重写整文件)与 merge-on-read(写 delete 文件,读时合并)。讲清 position delete 与 equality delete 的语义、字段与作用域规则,写放大/读放大的取舍,V2 delete file 到 V3 deletion vector(Puffin 承载)的差异与迁移,以及读路径如何把 data file 与 delete 合并出可见行。基于 pyiceberg 0.11.1 实测 CoW 写放大并观察 MoR 回退。
没有数据库进程,Iceberg 怎么在对象存储上做原子提交与并发控制?拆解提交=catalog 对元数据指针做 compare-and-swap,乐观并发如何基于当前 snapshot 生成新 snapshot、冲突按操作类型与隔离级别重试,不同 catalog 的原子性来源(DB 行锁/CAS、REST 后端、对象存储条件写、文件系统 rename),以及 REST Catalog 的 requirements+updates 提交语义。基于 pyiceberg 0.11.1 实测并发冲突与重试。
拆解 lakehouse 的两层基础:列式文件格式(Parquet/ORC/Arrow)与开放表格式(Iceberg/Delta/Hudi)。讲清没有数据库进程时,如何在对象存储上做 ACID、行级更新、快照与并发,以及 catalog、查询引擎、流式入湖如何拼成可运维的湖仓。面向数据平台工程师与从 OLAP/数仓转型的开发者。