01学完你能做到
- 解释 Parquet 文件和表格式分别负责什么。
- 用快照、时间旅行、分支和标签理解数据版本管理。
- 说清 schema evolution、partition evolution 与快照保留的取舍。
- 判断 Iceberg 适合数据湖中的哪些场景,以及它不能替代什么。
02这课解决什么问题
周一用 10 月的日 K 做回测,周三上游更正了几只股票的收盘价,数据团队覆盖了原来的分区。周五再次运行同样的参数,结果却对不上。怎样保留旧版本,让当时使用的数据可以被复现?
03从文件到表格式
Parquet 解决的是“一个文件内部怎样高效存储”;分区目录解决的是“怎样按日期或证券筛选文件”。但一张表由哪些文件组成、当前版本是哪一版、一次修改是否完整提交,这些问题还需要额外的表格式来管理。
表格式可以理解为数据文件之上的一层目录和版本记录。Apache Iceberg 的表状态保存在元数据中,元数据会记录 schema、分区规范和快照等信息;manifest 则记录快照引用的数据文件及其统计信息。读取者先加载表元数据,再根据当前快照决定读取哪些文件。
04快照与时间旅行
快照(snapshot) 是表在某一时刻的完整状态。追加、删除或覆盖数据后,表会产生新的快照;旧快照仍可能被读取,前提是它还没有被清理。
时间旅行(time travel) 是按时间点或快照标识读取历史状态。以 Spark SQL 为例,Iceberg 支持按时间点或版本读取;不同引擎的具体语法可能不同,应以所用引擎的文档为准。
快照有两个重要作用:
- 复现:回测或审计可以引用一个明确的快照,避免当前表变化后无法重现。
- 回滚与比较:可以查看历史状态,比较不同版本的文件和记录变化。
重要的业务版本可以用标签(tag)命名,例如 backtest_v1;需要继续写入、验证后再合并的场景,可以使用分支(branch)。标签和分支都是指向快照的命名引用,不是把数据复制一份。
05原子提交与并发读取
写入者通常先生成新的元数据文件,再通过 Catalog 更新当前元数据指针。读取者使用自己加载到的快照,在刷新之前不会看到一半完成的写入;并发写入发生冲突时,写入方需要重新读取最新状态并重试。
这带来一种很有用的隔离效果:读者看到的是一个完整快照,而不是“部分文件已经换了、部分文件还没换”的中间状态。具体的提交机制由 Catalog 和计算引擎共同决定,不能把某个 SDK 的实现细节当成所有 Iceberg 部署都一样。
06Schema evolution 与 partition evolution
Iceberg 支持在元数据层演进表结构,例如增加、删除、重命名列,或在允许的类型范围内扩大类型。符合这些规则的 schema evolution 通常不要求重写已有数据文件;新增列在旧文件中没有值,读取时要按引擎规则处理缺失值。
分区方式也可以演进。例如,表最初按月分区,后来改为按天分区。旧文件保留原来的分区布局,新写入的数据使用新的分区规范;查询通过表格式读取,不需要把分区字段直接写死在业务代码里。分区演进并不等于自动把所有历史文件重新整理一遍,是否重写要根据查询性能和维护成本另行决定。
07在金融数据链路中的位置
采集 / 批处理
│ append、overwrite
▼
Catalog ── 当前元数据指针
▼
表元数据 ── schema、分区规范、快照
▼
manifest ── 数据文件清单与统计信息
▼
Parquet 等数据文件
├─ 当前查询
├─ 历史快照 / 标签:回测复现、审计
└─ 快照过期:清理无须长期保留的历史文件表格式位于存储文件和查询引擎之间。它适合数据湖中的历史数据、批量回测和需要版本复现的场景;它不等于在线数据库,也不负责实时行情分发。高频小批量写入仍可能产生大量小文件和快照,需要通过合并、分区设计和维护任务控制成本。
08金融场景中的两个“时间”
Iceberg 快照记录的是数据系统何时提交了某个表状态。它不自动表示上市公司公告何时发布,也不自动保证回测没有前视偏差。
例如,某份财报在周三公开,数据团队周四才采集入库:
- 快照时间回答“系统何时写入了这份数据”;
- 公告时间回答“市场何时可能知道这份数据”;
- 回测还要按第 19 讲的
publish time、ingested_at和as_of过滤。
因此,工程层的 Iceberg 快照和业务层的版本字段可以同时使用:前者帮助复现文件状态,后者表达首发、更正和重述等业务事实。
09快照保留与存储成本
只要历史快照仍引用旧数据文件,这些文件就不能被安全删除。快照过期后,还要根据部署方式清理不再被引用的元数据和孤儿文件。标签或分支通常可以帮助重要版本按更长的策略保留,但具体保留行为要看引擎和 Catalog 的配置。
所以“能时间旅行多久”不是免费的能力:保留期越长,历史文件、元数据和维护成本通常越高。日常快照可以短期保留,发布版本或审计版本可以用标签长期保留;这是业务要求与存储成本之间的取舍。
10常见误区
- 把 Parquet 当成完整的数据版本系统:Parquet 只描述文件格式,不能单独管理一张表的快照、并发提交和历史引用。
- 以为 Iceberg 快照就是 Point-in-time 数据:快照是系统提交版本;回测还要保存公告时间、入库时间和业务版本。
- 随便挑一个快照做审计:一次复杂写入可能产生多个中间状态。应引用明确的业务快照、标签或发布版本。
- 以为 schema evolution 会自动填充历史数据:增加列不会凭空为旧文件生成历史值,读取时要处理缺失值。
- 永久保留所有快照:旧文件和元数据会持续增长,应按业务要求设置过期和清理策略。
- 把 Iceberg 当在线查询库:它更适合数据湖和批量场景,实时服务仍要结合合适的流处理和在线查询方案。
- 忽略 Catalog:Catalog 维护表当前元数据的位置。Catalog 配置或高可用设计不当,可能导致不同读取方看到的表状态不一致。
11延伸阅读
12一分钟讲给别人
试着用自己的话讲一遍Parquet 只管文件怎么存,Iceberg 再往上管哪些文件组成一张表,以及这张表经历过哪些版本。每次写入生成快照,可以按时间或版本读回历史状态,重要版本还能打标签。代价是旧快照会保留旧文件,需要定期清理。注意,快照表示系统什么时候提交,不等于财报什么时候公布,防前视偏差还要保留业务时间。
6 道自测
先在心里答一遍,再展开对照。能说清理由,比答对数字更重要。
01Parquet 和 Iceberg 分别解决什么问题?
02什么是快照,时间旅行依赖什么?
03原子提交对读取者有什么意义?
04schema evolution 和 partition evolution 为什么通常不要求重写所有旧文件?
05Iceberg 快照时间为什么不能代替公告时间?
06为什么要设置快照过期和清理策略?
已看 0/6 题
练动手练习
任务:设计一张日 K 表的版本方案。写出你会保留的 schema、分区规范、快照或标签命名,以及回测查询时需要同时使用的业务时间字段。再说明如果按月分区改成按天分区,旧文件和新文件应如何共存。
完成这一课
读完讲义、看完自测答案,这一课就算学完了。
- 读完讲义
- 看完全部自测
本课为投资者教育内容,案例数字均为示意,不构成任何投资建议,也不承诺收益。规则和费率会变,实际操作前请以交易所、监管机构和产品的最新公告为准。