Catalog Bullshit:把数据库拆开,再租给你一张 PostgreSQL 表

Catalog Bullshit:把数据库拆开,再租给你一张 PostgreSQL 表

💡 原文中文,约7800字,阅读约需19分钟。
📝

内容提要

文章剖析湖仓Catalog本质:它只是替对象存储保管表指针,核心是一次单行CAS,底层多为PostgreSQL。随着S3支持条件写,独立Catalog技术必要性下降,却成新收费点。治理难题源于控制面不在数据路径上,撤权、行级安全等只能靠引擎自觉。作者主张元数据回归数据库,DuckLake、pg_lake即此路线。

🔎

延伸解读

Catalog 的本质:一次单行 CAS

文章指出,Iceberg 提交写入的核心是让 Catalog 把表指针从旧 metadata.json 原子换成新的,等价于一次单行 compare-and-swap。Hive Metastore、Nessie、Polaris、Lakekeeper 等底层多依赖 MySQL 或 PostgreSQL。理解这一点,就能判断独立 Catalog 是否必要:它主要解决对象存储早期缺乏原子条件写的问题,而非提供不可替代的复杂能力。

治理难题的根源:控制面不在数据路径上

湖仓把数据放在 S3,Catalog 只能通过 credential vending 发放短期 STS token。token 一旦发出,Catalog 便退出数据路径,无法观察引擎实际读了哪些行和列。因此行级安全、列掩码只能依赖引擎自觉执行;REVOKE 也要等 token 过期才生效。撤权缺口和策略漂移首先是这种架构的结构性结果,而不是多引擎数量本身造成的。

元数据回归数据库:DuckLake 与 pg_lake 的路线

文章主张把 Catalog 和元数据放回 SQL 数据库。DuckLake v1.0 用 28 张表管理元数据,支持小文件内联和跨表事务;Snowflake 开源的 pg_lake 也让 PostgreSQL 直接充当 Iceberg Catalog。这条路线能利用数据库已有的事务、权限和目录能力,但文章也提醒,PostgreSQL 分析执行仍弱,实际常需借助 DuckDB 的向量化执行器。

开放一层,收费站上移一层

文章梳理了近年收购:Snowflake 收购 Crunchy Data 后开源 pg_lake,Databricks 收购 Mooncake Labs 和 Neon,DuckLabs 与 AWS 签署收购协议。其判断是,厂商并不阻止开放格式,而是确保开放的那一层不是自己收钱的那一层。格式开放就卖 Catalog,Catalog 开放就卖治理。读者可据此关注治理层是否成为新的锁定点。

❓

Q&A

湖仓架构里的 Catalog 到底解决了什么问题?

Catalog 的核心职责是替对象存储保管表的当前指针。以 Iceberg 为例,一次写入提交需要写新数据文件、manifest 和 metadata.json,最后让 Catalog 把表的当前指针从旧 metadata.json 原子地换成新的,这本质上是一次单行 compare-and-swap。这次原子换指针是 Catalog 唯一不可替代的职责。

为什么说独立 Catalog 的技术必要性正在下降?

早期 S3 没有原子 rename 和安全的 compare-and-swap,所以提交点只能交给外部协调者,Hive Metastore、Glue、Nessie、Polaris 等因此出现。2024 年 S3 开始支持条件写,对象存储能直接表达 create-if-absent 和基于 ETag 的条件更新,提交原语回到存储层,一部分工作负载不再需要独立协调者。

湖仓治理为什么比数据库治理更难?

数据库里引擎是访问字节的唯一入口,ACL 挂在门上,权限能成为强制边界。湖仓把数据字节放在 S3 里,谁拿到桶凭证谁就能直接读取对象。Catalog 只能做 credential vending,发出有时效和前缀限制的 STS token,但凭证发出后 Catalog 就退出数据路径,无法观察引擎读了哪些行列,因此行级安全和列掩码只能依赖引擎自觉执行。

湖仓里的撤权缺口是怎么回事?

如果 Catalog 发出一个有效期一小时的 token,随后管理员在控制面执行 REVOKE,已经签发的 token 仍然可以继续使用直到自然过期。因此撤权在这种架构里天然是异步的、最终一致的。把四个引擎缩减为一个并不会消除这个窗口,只要数据面仍然是 S3、外部表仍通过短期凭证直读对象,缺口就仍然存在。

DuckLake 把元数据放回数据库后带来了哪些实际好处?

DuckLake v1.0 采用元数据放在 SQL 数据库的路线,数据仍是 Parquet 并放在用户自己的桶里。它支持 data inlining,低于阈值的插入和删除先进入 Catalog 数据库的内联表,积累后再刷成正常文件,默认阈值 10 行,可维持约每秒 100 次事务。同时,元数据位于真正的数据库里,跨表事务可以直接使用底层数据库事务,让多张相关表一起 BEGIN、一起 COMMIT。

文章对“PostgreSQL 吃下数仓”这个说法怎么看?

文章认为需要换一个主语:真正吃下数仓的,是穿着 PostgreSQL 马甲的 DuckDB。PostgreSQL 执行器采用逐行火山模型,没有向量化执行和原生列存,分析扫描比 DuckDB、ClickHouse 慢一到两个数量级。pg_lake、pg_duckdb、pg_mooncake 等扩展的解决办法都是让 PostgreSQL 负责规划和事务,而把 DuckDB 的向量化执行器嵌入或另起进程运行。

🏷️

标签

➡️

继续阅读