
对象存储正在吞掉数据湖:S3 Tables 把 Iceberg 收编成存储的原生能力
一套 50TB 的 Iceberg 湖仓跑在 S3 上,某天一条 SELECT count(*) 跑了 40 秒。你以为是扫描慢,翻 metrics 才发现 80% 的时间花在 LIST 请求上------查询引擎为了拿到最新 manifest,把几万个小文件挨个列了一遍。这不是个例:当你把 data file、manifest file、独立 catalog(Glue / Unity / Nessie)分开养,湖仓的元数据就成了三套系统各自记账的「双重账本」。最近 MinIO 把 AIStor Tables 推进了稳定版(2026-07-24),RustFS 也在 6 月宣布原生支持 S3 Tables------对象存储正把「表格式层」吞进自己肚子里。
先说清楚:表格式层到底是什么
Iceberg 这类表格式,本质是在对象存储的扁平 K/V 之上盖了一棵「元数据树」:
- 一个 snapshot 指向一份 manifest list;
- manifest list 列出若干 manifest 文件;
- 每个 manifest 记录一批 data file 的字段范围、分区、行数。
查询引擎先读 snapshot → manifest list → manifest,才能精准定位「该扫哪些 data file」,而不是全桶 LIST。问题出在传统做法里这棵元数据树和 catalog(谁拥有哪个 snapshot、当前版本号多少)是分开部署的:对象存储只管 data file,catalog 另起一个服务,二者靠应用层对账。结果就是运维三件套------对象存储、catalog 服务、查询引擎,哪个抖一下湖仓就抽风。
把这套树收进存储之后,读写路径变成了这样:

MinIO 的做法:把 Iceberg catalog 收编进存储
AIStor Tables 在 2026-07-24 进入稳定版(此前只在 edge 构建里)。它把一个托管的 Apache Iceberg catalog 直接架在对象存储内部,跟着存储一起伸缩。公开 release notes 点名的几件事:
- 分布式 compaction:集群协调 Iceberg 表的合并,带 per-table 的 compaction-filter;
- snapshot expiration:warehouse 级可配快照历史过期;
- UFR(Unreferenced Files Removal):回收过期快照、失败写入留下的孤儿 data file,含 site-replication 副本;
- tag-based access control:表标签接入 IAM,按 tag 授权/拒绝;
- site replication:warehouse、catalog、namespace 跨站点复制,failover 后还能 resync。
用 MinIO 自己的客户端起一个表桶,接口形态大致是这样:
bash
# 创建一个 table bucket(Iceberg 表的命名空间容器)
mc alias set aistor https://tables.minio.local:9000 $KEY $SECRET
# 之后用标准 S3 Tables 接口建 namespace / 写 manifest
aws s3tables --endpoint-url https://tables.minio.local:9000 \
create-table-bucket --name my-lakehouse
上面是接口形态的示意,具体子命令以你部署的 AIStor 版本为准。重点是------建表、写 manifest、回收孤儿文件,现在都在存储这一侧完成。
RustFS 的同向:S3 兼容 + 原生表格式
RustFS 在 2026 年 6 月也宣布了对 S3 Tables 的原生支持,定位是「S3 兼容对象存储升级为 AI-native 存储」。对已经用 RustFS 跑 S3 工作负载的团队,这意味着不用再外接一个 catalog 服务就能直接挂湖仓负载,接入层还是那套 S3 API。开源协议是 Apache 2.0,没有商业 license 的绑定。
几家的现状摆在一起看更清楚:

真账怎么算:你方便了,也让渡了东西
把表格式收编进存储,省的是运维和 metadata 税,代价也很明确:
- 跨引擎可移植性被削弱。表格式标准还是 Iceberg,但 catalog 的实现、compaction 的语义、UFR 的回收策略,现在都长成了存储厂商的形状。今天用 MinIO 的 Tables,明天想迁去别家,catalog 这层不是简单 copy 就完事。
- compaction 是后台债,不是免费午餐。合并小文件、过期快照要算 CPU 和 IO。表多了、写入猛了,后台 compaction 会跟前台写抢资源,得配限速和窗口。
- 孤儿文件不会自己消失。UFR 是 MinIO 给的能力,但得确认它在你的部署里真正开着、且覆盖到 replication 副本;否则孤儿 data file 照样吃你钱。
- license 边界。MinIO AIStor 是商业许可,社区版(已归档的 MinIO CE)不含 Tables;RustFS 走 Apache 2.0。这层要算清法律和预算。
S3 Tables 解决的是「元数据账本散落」的老问题,但别当成万能药------它把复杂度从「你运维三套系统」挪到了「你信任厂商的 catalog 实现」。
结尾给动作:先别盲目上
如果你的场景符合下面任一条,建议先用外部 catalog 撑着:
- 表要被多个异构引擎(Spark、Trino、DuckDB、ClickHouse)同时读写,且你要在引擎间自由迁移;
- 合规要求 catalog 完全自己掌控、不出存储厂商边界;
- 当前湖仓规模小,compaction 自己写个定时任务就够用。
如果符合下面这些,可以认真评估 S3 Tables:
- 主要走 S3 API 单一技术栈,不想再养一个独立 catalog 服务;
- 写入碎片化严重(Iceberg 高频产出 MB 级 Parquet),被孤儿文件和 LIST 风暴拖垮;
- 需要跨站点复制 warehouse + catalog 一起 failover。
动手前先跑这条命令,看清自家桶的 LIST 压力是不是真瓶颈:
bash
# 统计某前缀下 object 数,粗略判断 LIST 负担
aws s3 ls s3://my-lakehouse/warehouse/ --recursive --human-readable | wc -l
# 若单表 manifest 下挂几万 data file,且查询 P99 卡在 LIST,
# 才是 S3 Tables 真正该上的信号
RustFS 把 S3 Tables 作为原生能力开放出来,意味着自建湖仓少了一个外接 catalog 的包袱:同样的 S3 API,既能当对象存储,也能直接挂 Iceberg 负载。
仓库在这:https://github.com/rustfs/rustfs 。先拿开发桶跑通 compaction 和孤儿回收,再决定要不要把生产湖仓迁过去。