LanceDB 0.40.0 把物化视图与远程目录一起落进多模态湖;DuckDB 用几百 KB 的库文件当整个数据湖的目录;Google 把 Iceberg REST 目录架在 Spanner 上;Polars 2.0.0 把流式排序与湖格式下推做进执行层
本期聚焦 10 月 6 至 7 日的四件事:LanceDB 0.40.0 基于 Lance 13.0.0 发布,把物化视图、远程目录、命名空间化 Secrets 与 zonemap 索引一起交付;DuckDB 用一篇短文把「只存视图定义、不含一行数据」的库文件讲成可共享的目录;Google Cloud 公开 Lakehouse runtime catalog 的底座细节,把 Iceberg REST 目录跑在 Spanner 上;Python 侧 Polars 从 1.44.2 直接跳到 2.0.0,改动集中在流式执行与 Iceberg/Lance 的下推。
10 月 6 日到 7 日这两天,数据基建的动静被同一个词串起来:catalog。它不是新概念,这两天却在两个极端上各被重做了一次。DuckDB 发了一篇六分钟的短文,说明一个 DuckDB 库文件可以不存任何数据,只存指向对象存储上 Parquet 文件的视图定义,于是几百 KB 的文件成了一个可挂在 URL 上分享的目录。同一天,Google Cloud 公开了 Lakehouse runtime catalog 的底座:原生实现 Iceberg REST Catalog 规范,后端跑在 Spanner 上,靠水平扩展与可串行化事务去接住「Agent 反复发起大量小查询」这种负载。LanceDB 0.40.0 也在同一天发布,把物化视图、远程目录与命名空间化的 Secrets 一起交付,让多模态湖里第一次有了「查询即定义」的预计算对象。Polars 2.0.0 落在引擎这一侧:Python 包从 1.44.2 跳到 2.0.0,改动最密的两处是流式引擎补上外存排序、以及把谓词与元数据缓存推进 Iceberg 与 Lance。四件事分处两端,动作其实一致——查询的对象从「一组文件路径」变成「一个可寻址的名字」,而这个名字背后该有多少基础设施,成了各家真正要回答的问题。
LanceDB 0.40.0:物化视图、远程目录与可寻址的 Secrets 一起落地
事件概述
10 月 7 日,LanceDB 发布 v0.40.0 稳定版,底层切换到 Lance 13.0.0,维护分支为 release/v0.40;Java 侧对应 Maven 坐标 com.lancedb:lancedb-core:0.40.0。同日还发出了 v0.41.0-beta.0,beta 线继续并行推进。
这一版最显眼的是物化视图。LanceDB 此前的定位是「多模态数据的存储与检索库」,索引与查询是核心,预计算对象是缺的一块。0.40.0 把物化视图做成由查询定义的实体:视图的定义就是那条查询,而查询的 FROM 位置可以是已经在库里注册过的 Function。配合同一版里的 GROUP BY 支持,物化视图可以先按普通分组键聚合,也可以按某个向量列的 IVF 分区分组——后者意味着预计算单元与向量索引的物理布局对齐。刷新环节相应拆细:支持分区刷新,IVF 分组的物化视图可以按 unit 逐个刷新,drop_view 与 drop_function 都会返回一个清理作业而不是直接删掉东西。
第二块是远程目录。0.40.0 加了 remote catalogs 以及 Python、TypeScript 两侧绑定,配套补上 view CRUD API 与远程侧的物化视图 API。目录从此不再是本地进程里的一个对象,而是可以被客户端寻址的服务端点。
技术解析
- 物化视图由查询定义:
feat: define a materialized view by its query, with Functions in FROM position(PR #4190)确立了定义方式;#4222 补上GROUP BY;#4223 支持「按某向量列的 IVF 分区分组」;#4232 让 IVF 分组的物化视图以 unit 为单位刷新;#4303 在 SQL 层加了原生向量去重与分区化刷新。 - Function 的身份与寻址:#4176 把已注册 Function 用 OCI 镜像身份表示,#4341 支持按命名空间路径寻址 Function,#4231 在其输出列被删除时自动退役对应绑定。Function 从「一段用户代码」升级成「一个有地址、有身份、有生命周期的对象」。
- Secrets 命名空间化:#4150 引入具名 Secrets、bindings 与命名空间寻址。凭据不再是散落在连接参数里的字符串,而是目录里可引用、可按命名空间隔离的实体。
- 鉴权链路补齐:#4182 增加持久化 OAuth token 缓存与 session API,#4181 改用
oauth2crate 并允许配置客户端认证方式,#4193 支持 OIDC 的 resource 与 audience;#4179 顺手把认证头从 debug 日志里抹掉。 - 索引侧:#4199 新增 zonemap 索引构建器,#4206 放宽其类型支持;#4205 一次性补上 NGram、BloomFilter、RTree 三类索引构建器。
- 作业控制:#4112 让 Python SDK 可以暂停和恢复作业,#4208 允许客户端列出某张表上逐行的 Function 错误。
- 破坏性变更:官方在 release notes 里单列了 10 条 breaking changes,覆盖 OAuth 会话、远程物化视图 API、Secrets 寻址、Function 寻址、Node 侧对象行取值等,升级前需要逐条对照。
行业影响
LanceDB 做物化视图,信号不在「多了一个 SQL 对象」,而在多模态湖开始接受和传统数仓一样的成本模型。多模态数据的典型负载是「对一批样本反复做同一种计算」——重跑 embedding、按标量条件回捞、语义去重、正负样本生产;这些负载和分析型物化视图的负载形状相同:写少读多、结果可增量维护。把预计算对象做进存储层,等于承认多模态湖不会永远停留在「存进去、检索出来」这一步。
Function 的身份化是更值得盯的一处。用 OCI 镜像身份表示已注册 Function,等于把「这段计算跑的是哪个版本的代码」变成了目录里可校验的字段;配合具名 Secrets 与命名空间寻址,整条「谁用哪个凭据、跑了哪个镜像、产出哪几列」的链路可以被目录追下来。多模态管线最容易失控的地方正是这里——同一个向量列,不同批次由不同版本的代码产出,事后无法归因。
相关链接
DuckDB:一个不含任何数据的库文件,可以当整个数据湖的目录
事件概述
10 月 7 日,DuckDB 团队发了一篇六分钟的短文《A DuckDB Database with No Data in It》,把一个已经在社区里流传两年的想法写成了可操作的模式:DuckDB 的库文件不必存任何数据,它可以只存视图定义,而每个视图指向对象存储上的 Parquet 文件。文件本身体积维持在几百 KB,不随它所描述的数据量增长;任何人把它 attach 上去,就得到一组可以直接查询的具名关系。
文章把它定位成「一个可分享的小目录」。发布方可以把这个库文件传到任何 DuckDB 能通过网络读到的位置——s3:// 桶或者一个 https:// 端点,放在存 Parquet 的同一个桶里最方便。分享从此不再是发一串文件路径,而是发一个 URL。
技术解析
- 视图只存查询文本,表才存行:表把行写在库文件里;视图只存一条查询的文本,读视图时 DuckDB 现场执行这条查询。如果查询读的是远端 Parquet,数据就留在对象存储,视图里只有「怎么读」这条指令。
- 构造方式:先
INSTALL httpfs,然后ATTACH 'rail_catalog.duckdb' AS rail; USE rail;,再CREATE VIEW services AS SELECT * FROM 'https://blobs.duckdb.org/train_services.parquet'。位置必须写成完全限定形式(远端 URL 或绝对路径),否则视图会随客户端工作目录变化而失效。 - 数字:示例里的
train_services.parquet有 380,959 行,而读它的目录文件是几百 KB。 - 只读挂载:消费方用
ATTACH 'https://example.com/rail_catalog.duckdb' AS rail (READ_ONLY);挂载,每次查询都去读引用文件的当前内容。DuckDB 只取查询需要的列与 row group,带过滤或聚合的查询不会整份下载。 - 布局变更对消费方透明:单个 Parquet 太大而按年拆分时,发布方只需
CREATE OR REPLACE VIEW services AS SELECT * FROM read_parquet('s3://my-bucket/rail/services/year=*/*.parquet');后续批次把station_name改名成station时,视图可以用* EXCLUDE (station), station AS station_name把列名映射回消费方已经在用的名字。 - 三条限制:消费方除了目录文件本身,还要能访问它引用的每一个数据源;HTTPS 与 S3 API 上的连接是只读的,改视图只能改本地副本再上传;查询性能取决于网络与引用文件的布局。
- 出处与配套:文章点名 Nikolas Goebel 的《DuckDB doesn’t need data》(2024-05-28)作为思想来源,并为该模式配了一份独立指南《Share a DuckDB Database That Only Stores Views》。
行业影响
这件事的意义在于把目录的门槛降到了几乎为零,代价是它的边界也被暴露得很清楚。一边,任何团队都能用几百 KB 的文件给自己的数据湖配一层语义层:视图定义里编码了推荐的 join、过滤条件与列名,消费方拿到的是「该用的名字」而不是「文件在哪」。这比传统的做法是轻得多的——不需要部署任何服务,不需要外部元数据数据库。
另一边,文章给出的三条限制正好划出了它不能替代什么。没有访问控制:谁能读这个 URL,谁就能读目录里所有的视图;没有写入语义:HTTPS/S3 上的连接只读,改视图要重传整个文件;没有查询端的优化保证:性能完全取决于远端文件怎么切。换句话说,它解决的是「命名与解耦」,不解决「权限、一致性、治理」。这是把它和本期另一条 Google 的公告放在一起看才有意思的地方——同一个 catalog 抽象,一边做到几百 KB,一边做到 Spanner。
还有一处容易被忽略:视图让「发布方改物理布局」与「消费方改查询」解耦。分区方式变、桶变、列名变,都只需改目录。这条能力在所有目录系统里都有,但只有当目录轻到可以随便重建时,改动成本才真的接近于零。
相关链接
- A DuckDB Database with No Data in It(DuckDB Blog, 2026-10-07)
- Share a DuckDB Database That Only Stores Views(DuckDB 文档指南)
Google Cloud:把 Iceberg REST 目录架在 Spanner 上,理由是 Agent 会反复发小查询
事件概述
10 月 7 日,Google Cloud 发了一篇八分钟的文章,公开 Lakehouse runtime catalog 的底座设计。这个目录已 GA,原生实现 Apache Iceberg REST Catalog 规范,后端跑在 Spanner 上。文章没有宣布新特性,而是回答「一个托管目录到底要解决什么」,以及为什么用 Spanner 来解。
给出的动机值得原样记下来:大型企业做湖仓改造时发现,需要一个高可扩展、高可用的托管目录;而当查询随 Agent 扩展时,这一点更紧要——为了支持 Agent 发起的大量重复小查询,目录必须提供大规模下的原子性、一致性、可用性与并发能力。
技术解析
文章先列了托管目录必须解决的五件事,再逐条对应到 Spanner 的能力:
- 原子提交与并发控制:Iceberg 用乐观并发控制(OCC)保证 ACID,托管目录必须实现一个可靠的原子 CAS 来替换当前元数据指针。Spanner 提供多表 ACID 事务与可串行化隔离——数据库内事务的顺序与客户观察到它们提交的顺序一致。
- 高可用与运维:目录挂了查询立刻失败,这把它推成了 Tier-1 服务。Spanner 的区域配置提供最高 99.99% 的可用性。
- 后端库的扩展:传统纵向扩展的关系库在并发读写压力下会撞上 CPU、内存、存储与连接数的天花板,手工分片又会带来巨大运维负担;横向扩展的系统则在一致性、可管理性或企业级能力上妥协。Spanner 的做法是:无需手工分片,计算与存储独立透明地扩展;按数据量与查询负载动态切分并在节点间重分布;计算节点按 CPU 利用率与存储阈值动态伸缩;自动检测 split 级过载并把热点 split 迁走。
- 表维护协调:目录本身不优化数据,压缩、快照过期、manifest 重写、孤儿文件清理都要另外建管线。
- 治理与安全:目录是安全闸门,要实现认证协议(OAuth2 token exchange、IAM 联邦)、namespace 与 table 级的访问控制,以及 vended storage credentials——签发短时效令牌,让查询引擎不必持有宽泛的存储凭据。
架构侧给出几条可以直接引用的事实:
- 零数据拷贝:表定义直接指向对象存储里已有的数据,不移动、不重写、不复制。
- 双向跨云目录联邦:通过支持 vended credentials 与 OIDC token exchange,可以访问 Databricks Unity、Snowflake Horizon 与 AWS Glue 中的数据。
- 凭证模式可选:credential vending 与 end-user credentials 二选一,引擎可以不直接接触底层对象存储(Cloud Storage、AWS S3、Azure Blob Storage)的文件。
- 检索与治理:目录直接集成 Knowledge Catalog 与 Cloud IAM。Knowledge Catalog 用 Spanner 的全文检索加上原生向量检索做召回,两类索引建在同一份基表上,与基表 DML 以事务性 ACID 一致更新,同步管线与外部检索系统这两套运维负担随之消失。
- 客户数字:Etsy 把目录迁移到 Lakehouse runtime catalog,就地 join 数据,管线查询提速 60%。
行业影响
把目录的后端选型摆到台面上讲,是这篇最值得读的部分。它把行业里一个长期含糊的权衡说清楚了:目录的元数据量不大,但它的读写模式极不友好——大量并发的小事务、每一次都要强一致的 CAS、任何不可用都立刻传导到查询。用纵向扩展的关系库,撞天花板只是时间问题;手工分片则把运维成本转嫁给用户;用最终一致的系统,就要放弃 Iceberg 承诺的提交语义。Spanner 这类底座的价值正在于此:关系语义照给,水平扩展也照给,在这个特定负载上它成了少见的合理解。
把 Agent 写进动机里也不只是修辞。人的分析查询是低频、大扫描、可容忍秒级元数据延迟;Agent 的查询是高频、小扫描、且常常是同一个语义问句被反复提交。前者对目录的压力在吞吐,后者在并发与尾延迟。目录从「给引擎查表在哪」变成「给 Agent 提供可信上下文」,选型标准就变了。这也解释了 Knowledge Catalog 为什么被放在同一篇里讲:目录要承担的不只是定位,还包括「让 Agent 找得到、且找对了」——全文与向量检索与基表事务一致地更新,正是为了让检索结果不会比数据旧。
相关链接
- Managed Apache Iceberg at scale: How Spanner powers Lakehouse runtime catalog(Google Cloud Blog, 2026-10-07)
- Amazon Redshift adds support for creating and refreshing Apache Iceberg materialized views(AWS What’s New, 2026-10-05)
- Apache Beam 2.77.0 release notes(GitHub, 2026-10-07)
Polars 2.0.0:大版本跳号,改动最密的两处是流式执行与湖格式下推
事件概述
10 月 6 日,Python 包 Polars 2.0.0 发布,上一个稳定版是 9 月 9 日的 1.44.2。两个 RC 分别出现在 9 月 2 日与 9 月 20 日。这一版没有单独的宣告文章,release notes 直接给出破坏性变更与一长串性能条目。另一个细节是 Rust 侧 crate polars 的公开版本号仍停留在 0.55.x 线上,Python 侧的版本线与 Rust 侧并不对齐。
从条目密度看,这一版的工作集中在两个方向:流式(streaming)引擎补齐它在超内存场景下缺的能力,以及把谓词下推与元数据缓存推进 Iceberg 与 Lance。
技术解析
破坏性变更一共六条,全部指向语义收敛:
- SQL 窗口函数在分组行上对聚合后的行求值,并且
QUALIFY在投影之前求值(#29746)。 - 精确的 SQL 数值字面量类型化为 Decimal,SQL 的
%与DIV做截断(#29536)。 - 确定性的表达式插件可以选择性加入 CSE/CSPE(#29428)。
- Parquet 的 ENUM 类型读成
pl.String(#29331)。 - map 操作扩充(#29296)。
cut/qcut进入弃用(#29329)。
流式引擎这一侧,最关键的三条是:
- 新增流式(外存)排序(#29657)——此前排序是流式引擎里最容易把内存打爆的算子。
- 流式 GroupBy 的热表大小改成动态(#29629),并让开启一段等值键的首个键直接进热表(#29673)。
- 只在有内存余量时才在 unspill 时预取(#29701),以及不内联慢路径上的 OOC 内存漂移(#29745)。
- 配套还有:固定大小滚动窗口在流式引擎上执行(#29602)、group-by 节点被标记为内存密集型管线阻塞点(#29749)、不在流式引擎里缓存普通扫描(#29654)。
与湖格式相关的条目是另一条主线:
- 跨扫描缓存 Iceberg manifest 文件(#29623)——同一会话内多次扫描不再重复拉 manifest。
is_nan/is_not_nan过滤下推到 Iceberg(#29579),str.starts_with下推到 Iceberg(#29545),可失败的 Hive 谓词下推支持改进(#29594)。- 过滤下推到
scan_lance(#29538)。 - 远端读路径:IPC 与 Parquet 在不要求保序时乱序解码(#29675、#29546),远端 IPC/Parquet 文件在不保序时不排序输出(#29678、#29581),IPC metadata 后缀单独拉取(#29692),远端 IPC 扫描的 record batch 抓取成组(#29750),小对象上传合并成单次 PUT(#29603),HTTP 限流器的初始读值上调(#29584)。
执行层的微观改造也占了一大块:join 与单键 group-by 的哈希表布局重做并加入预取(#29653、#29661、#29663),运行时过滤器在构建线程间共享同一个 bloom filter(#29677)、去掉构建侧的字节上限(#29618)、并能穿过 union(#29565),decimal 加减乘在值域允许时直接用 i64 计算并按车道并行求和(#29638、#29637、#29634),少数分组的 sum/mean/count 也改成车道更新(#29573)。
行业影响
Polars 2.0.0 释放的信号是:单机执行引擎的竞争正在从「单机有多快」转向「单机在湖上有多快」。外存排序、动态热表、unspill 策略这些改动,解决的是同一件事——数据量超过内存之后,行为是可预测的降级而不是失败。这让 Polars 在「一个节点读一整个湖分区」这类任务上有了更稳定的表现,而这类任务过去要么靠 Spark,要么靠手工分块。
把 Iceberg manifest 缓存、谓词下推到 Iceberg 与 Lance 放在一起看,方向更清楚:引擎在主动向开放表格式靠。下推的种类已经从「比较谓词」扩到 is_nan、str.starts_with 这类函数级谓词,说明引擎开始理解湖格式提供的统计信息能回答什么。这一步的代价是引擎与格式的耦合变深——下推规则要跟着格式的元数据能力走,格式换版本,引擎要跟着改。开放格式的承诺是「任何引擎都能读」,而真正读得快的引擎,正在变成那些愿意为每种格式写下推规则的引擎。
破坏性变更里那条窗口函数语义调整也值得单独提醒:窗口函数在分组行上对聚合结果求值、QUALIFY 提前到投影之前,都会改变已有 SQL 的结果。大版本跳号在这里是有意义的——它明确告诉使用者,语义已经变了,不要假设升级前后一致。
相关链接
编者评
本期四件事可以并成一张图来看,因为它们的分歧点只有一处:「一个名字」该由什么来背。DuckDB 的回答是一个几百 KB 的文件,谁拿到 URL 谁就能用,代价是没有权限、没有写入、没有优化保证。Google 的回答是一个跑在 Spanner 上的 Tier-1 托管服务,代价是它成了必须被运维、被计价、被纳入可用性目标的依赖。两个答案都不新鲜——轻目录和重目录在数据库史上都有先例——但把它们放在同一天看,能看清当前的选择标准是什么:不是数据量,而是谁来查。给分析师查,目录可以轻,因为查询少、人可以自己记路径;给 Agent 查,目录必须重,因为查询多、重复、且没人来兜底纠正。Google 那篇把 Agent 写进动机里,LanceDB 把物化视图做进存储层,Polars 把 manifest 缓存与谓词下推做进引擎,其实都是同一个判断的不同表达:读取方正在从人变成程序,而程序不会记得路径,只会反复问同一个名字。
还有一条更细的线索值得盯住:这四件事里有三件都在处理「名字之后的那一层」——LanceDB 用 OCI 镜像身份标记 Function、用具名 Secrets 隔离凭据;Google 用 vended credentials 与 OIDC token exchange 做跨云联邦;DuckDB 干脆不做这一层,把三条限制写清楚让使用者自己补。目录的价值从来不在「表在哪」,而在「谁有权用、用的是哪份代码、结果什么时候算的」。当目录轻到几百 KB 时,这一层必须由使用者自己搭;当目录重到 Spanner 时,这一层由服务来兑现。真正决定选型的是这一层的归属,不是目录本身的大小。
本期中文源仍然没有可用的对等内容。阿里云 MaxCompute、DataWorks、Hologres 与火山引擎 LAS、EMR、DataLeap 的公开文档页与开发者社区在同一窗口内没有可核验的数据基建类更新,页面抓取依旧只返回同一份前端外壳,本栏目已连续多期无法取得中文侧的一手进展,将持续跟踪并改用开源仓库的发布日期作为兜底线索。另有几条线索留到下期:Databricks 于 10 月 8 日宣布 Workday Data Connect 在 Unity Catalog 上的联邦;AWS 于 10 月 5 日让 Redshift 支持创建与刷新 Iceberg 物化视图(本期作为相关链接列出);Delta Lake 4.4.1(10 月 5 日)修补了目录托管表的维护安全性与 S3A Fast Listing 的快照构造问题;Apache Beam 2.77.0(10 月 7 日)让 BigQueryIO 可以用四段式标识读取 BigLake metastore 里的 Iceberg 表。