Parquet 统治十年后,WASM 能撬动它吗?
你有一张存了八年的 Parquet 表,数据量不大不小,三百多 GB。某天你接到一个新需求:对这张表做点查——不看全表扫描,就是按主键挑几十行。你试了一下,发现 Parquet 不是不能做,但每次都要从 row group 的 column chunk 里翻出目标页,页粒度动辄几十万行,I/O 开销跟需求完全不匹配。
你心想:列式存储格式搞了十多年,怎么连个像样的随机访问都做不好?
这正是 CMU 数据库组在 SIGMOD 上发表 F3(Future File Format)的起点。但也正是这个起点,踩进了格式之争中最敏感的那根弦。
一个新格式,一个老问题
F3 要解决的问题,用一句话概括:现有列式存储格式(Parquet、ORC)诞生于 Hadoop 时代,其存储布局和演化机制已经不适应当下的硬件和负载。 Parquet 的 row group 粒度粗、元数据层级扁平、列编码固化在规范中——新编码要落地,得等所有 reader 实现更新。而 F3 论文引用的一组数据颇值得玩味:当前使用最广的 Parquet 版本,仍然是 2013 年的 v1。
Parquet 自己都没能替代掉 Parquet 自己。
F3 的方案是双管齐下。在布局层面,它引入了一套更精细的层级结构:IOUnit(I/O 基本单元)→ EncUnit(编码基本单元,默认 64K 行)→ 可选的子 EncUnit 向量。这套层级允许 reader 在读取时做更细粒度的投影——想只拿一列中的某几千行?遍历 EncUnit 索引,跳过不相关的块即可。
在可扩展性层面,F3 的核心创意是将解码器以 WASM 二进制形式嵌入文件自身。每个 EncUnit 可以标记一个 WASM ID,指向文件尾部存储的解码器。reader 如果本地不认这种编码,直接加载 WASM 模块解码——不需要升级 reader 版本,不需要等社区达成共识。论文称 WASM 解码器体积在 KB 级别,“negligible storage cost”。
这就是 F3 的两张牌:更精细的随机访问,和用 WASM 绕开兼容性死锁。
数据背后是什么
F3 的 benchmark 对比了 Parquet、ORC、Vortex、Lance 和 Nimble。从论文的实验中可以看到几个趋势:
- 随机访问:F3 的点查延迟显著低于 Parquet,尤其是在只需要少数列和少量行的场景。这不是什么魔法——EncUnit 层级天然支持更小的 I/O 粒度。
- 压缩率与解压速度:大体与 Parquet 在同一水平线。F3 默认为每 64K 行一组的 EncUnit 使用 Cascade 编码(类似 Vortex 的默认编码),配合 Zstd/LZ4 压缩。没赢,但也没输。
- WASM 解码开销:使用 WASM 解码器比原生解码慢一档,但论文着力论证这个差距在可接受范围内。这里需要做一个工程判断:WASM 解码器的存在意义是保证”文件可读”。 它是 fallback,不是加速器。
综合来看,F3 在 benchmark 上呈现的是一个”在某些维度上有提升、整体不输 Parquet”的姿态。对于一篇 SIGMOD 论文,这个结果是合格的。对于一场格式替代战争,这个结果还不够。
兼容性:真正的护城河
HN 讨论区最高票的评论来自 vouwfietsman,他说了一句很残酷但很难反驳的话:
Parquet is unfortunately very good just by virtue of being first, and so widely supported.
Parquet 的生态位有多稳固?列举几个事实就清楚了:Spark、DuckDB、Pandas、Polars、Snowflake、BigQuery、Redshift Spectrum、AWS Athena、Trino、Presto、ClickHouse(外部表)……几乎所有叫得出名字的数据工具都原生支持 Parquet。它的规范是开放的,但在二十余个主流实现的反复磨合中,形成了一套事实标准。你生成的 Parquet 文件可以被任何工具读取——它是社区十年的 bug 修复和互操作适配堆出来的。
这就引出一个悖论:F3 试图用 WASM 解决”新编码无法被旧 reader 识别”的兼容性问题,但真正挡住新格式的是生态接入成本。
一家公司要切换到 F3,需要做什么?
- 所有下游查询引擎添加 F3 reader(WASM fallback 只能解码 EncUnit,不能替代完整的 reader 实现——文件头解析、元数据遍历、谓词下推、投影裁剪,这些都需要原生代码)。
- 所有数据管道(ETL/ELT)支持 F3 writer。
- 所有数据治理工具(catalog、schema registry、血缘追踪)能解析 F3 元数据。
- 数据共享的外部合作方能读 F3。
这不是一个 WASM 解码器能解决的。Parquet 的护城河是十年积累的生态织网。
WASM 方案的张力
F3 的 WASM 设计引发了 HN 上一场激烈的子讨论,焦点集中在三个层面。
第一层是安全性。 文件内嵌可执行代码,即便 WASM 沙箱再成熟,也天然触发了工程师的安全神经。有人类比 PDF 中的 JavaScript——标准设计了这项能力,但每个理智的 viewer 都会默认关闭它。F3 的支持者反驳说 WASM 解码器只是 pure function,无 I/O 能力,沙箱能限制指令数和内存上限。但数据工程的工作流往往涉及不可信来源的数据文件,允许任意 WASM 执行仍然是许多安全团队不会接受的选项。
第二层是性能定位。 vouwfietsman 一针见血地指出:列式存储格式的核心价值是用顺序扫描换取分析性能,牺牲随机访问。F3 把改进随机访问作为主要卖点,但随机访问本身不是列式存储的设计目标。如果优化了随机访问却让全表扫描变慢(哪怕只是 WASM 解码路径),那是在拿核心优势置换一个次要能力。
第三层是技术选型的自洽性。 F3 的元数据层使用了 Google 的 FlatBuffers 来序列化 schema 和文件布局信息。WASM 解码器需要在宿主语言和 WASM 内存之间来回传递数据,而 FlatBuffers 解析本身也需要一定的开销。有评论者认为,引入了 WASM 运行时 + FlatBuffers 序列化/反序列化的组合,等于在读取路径上加了两层抽象开销——这恰恰是列式存储希望尽可能精简的部分。
这些质疑不意味着 F3 的设计是错的。但它们指向一个核心命题:F3 试图解决的,是格式演进中的次要矛盾,而非主要矛盾。 主要矛盾是”如何让所有人愿意换”,不是”新编码怎么落地”。
历史的回声
HN 评论中有人贴出了 xkcd #927(“Standards”),有人提起了 OpenDoc 的命运——一个技术上更先进、但最终输给网络效应的文件格式。也有人认为不必如此悲观:如果 F3 在某些细分场景中提供了 Parquet 无法提供的价值(比如需要频繁随机访问的在线特征存储、或需要自定义编码的垂直领域),它不需要赢下整个市场,只需要在自己的生态位里站稳。
笔者倾向于认为,两种判断并非互斥。格式替代的历史确实一面倒地支持”兼容性优先”论,但历史上没有出现过”把解码器嵌入文件”这种设计。WASM 的出现改变了跨平台可执行代码的成本结构——十年前在文件中嵌入沙箱化执行环境是不可想象的,今天它只是一行 wasmtime::Module::new()。
F3 可能不会取代 Parquet,但它提出的 WASM 解码器范式,有可能会被 Parquet 或其他格式吸收。最好的结局不是替代,是污染——让旧格式学走你的好设计,你再奔赴下一块无人区。
从目前的趋势看
F3 目前仍然是一个研究原型——README 开篇即声明”不应在生产环境使用”,GitHub 上仅 4 次 commit,benchmark 复现脚本也尚未完整。它离”可以被工程团队认真评估替代方案”还有很长的工程化距离。
而从行业趋势看,Parquet 的地位短期内几乎不可能被动摇。Iceberg、Delta Lake、Hudi 这些开放表格式的崛起,进一步将 Parquet 固定在了湖仓架构的底层——表格式之争在往上层走,文件格式反倒被”锁定”得更深了。你不太可能一边切 Iceberg,一边又切底层的文件格式,那是两倍的迁移成本。
但 F3 提出的问题是有价值的。Parquet 的演化瓶颈是真实的——十年没动过的 v1 还在主导世界,这不是正常的状态。WASM 解码器这条思路,即便最终不成就 F3,也可能成就其他格式的某一版 spec。
换句话说:这不会是 Parquet 的葬礼,但它可能是下一代列式存储格式的第一声胎动。
参考:F3 SIGMOD 论文 · GitHub 仓库 · HN 讨论