DuckDB 2.0 alpha 把下载与解码拆成两池,S3 查询快 2 到 3 倍;Daft 0.7.25 给 Iceberg 补上静态分区覆写;Lakeflow Connect 收编 16 个营销数据源;Databricks 9 月发布记录把外来 Iceberg 表纳入共享
本期聚焦四条来自 9 月 10 至 11 日的进展:DuckDB 2.0 alpha 的实测数据、Daft 0.7.25 的 Iceberg 写入与读取补齐、Databricks 托管摄取扩到营销数据源,以及平台发布记录里共享与治理条目的推进。
9 月 10 到 11 日这两天,四件事各自发生在不同层次上,做的是同一类减法:把原本要重复做很多遍的活,改成只做一遍。MotherDuck 把 DuckDB 2.0 alpha 拉到自己的笔记本和 S3 上跑了一轮,读远程 Parquet 的耗时从 18.8 秒压到 7.7 秒,靠的是把下载和解码交给两批不同的线程;递归 CTE 引擎重写之后,遍历两万次提交的祖先链从 1.8 至 16 秒落到 0.10 秒,因为整张表只读了一次而不是每轮一次。Daft 0.7.25 给 Iceberg 写入加了
overwrite_filter,静态分区覆写不必再重写整表。Databricks 把营销栈里 16 个 SaaS 源收进 Lakeflow Connect 的托管连接器,广告报表开箱即有,企业不必为每个源写一遍 API 集成。9 月的平台发布记录里,OpenSharing 对外来 Iceberg 表的共享转为 GA,数据留在原处就能被共享,不必先复制一份。四处省掉的重复量级不同,留下的尾巴也不同:小文件读没有改善、VARIANT 的 list 转型反而更慢、自定义报表与 UI 路由仍未就位、外来表需要定期刷新才能保持最新。
DuckDB 2.0 alpha 实测:异步 I/O、递归 CTE 重写与 VARIANT 拆解
事件概述
MotherDuck 的 Mehdi Ouazza 在 9 月 10 日发表《Why DuckDB 2.0 is faster》,用一台 M5 笔记本和家庭网络对 2.0 alpha 做了实测。文章没有复述官方博客的声明,而是把三个他判断最影响建表和跑管线的人的特性各自跑了一遍,并附上数字。
这次实测的时间点值得留意。DuckDB 官方在 9 月 2 日切出 v2.0-cyanoptera 分支并宣布功能冻结(本专栏 Vol.60 已记录),此后进入的是只修 bug 的状态。换句话说,下面这些数字面对的是一份接近最终形态的代码,而不是早期原型。作者也给出免责:所有数字来自一台机器和一条家庭网络,两条链路对两个版本的影响大致相当,引用前应当自己跑一遍。
技术解析
- 异步 I/O 的做法:2.0 把取数和解码分给两批线程。1.5.5 里每个 worker 要下载、还要解码,等网络时 CPU 空转,解码时没有下载在飞,18 个 worker 最多只能有 18 个并发下载。2.0 用独立的下载池提前取回几十个 row group 存进缓冲区,worker 只负责解码,网络和 CPU 一并处于忙碌状态。
- 实测数字:一个 2.2 GB 的 Parquet(Stack Overflow votes,2.28 亿行,2268 个 row group)只读其中一列约 230 MB,1.5.5 用 18.8 秒,2.0 alpha 用 7.7 秒;23 个 Parquet 共 13.6 GB 读一列,11.8 秒对 3.9 秒;一个 1.7 GB 纯 CSV,116 秒对 55 秒。测试显式关掉了
enable_external_file_cache,保证每次都真的打到 S3。 - 不起作用的场景:30 个约 1 MB 的小 Parquet,3.7 秒对 3.3 秒,几乎没变化。原因是耗时来自每个文件的往返(先取 footer 再取数据),预读消不掉。作者的结论很直接——把湖存成上千个 1 MB 文件本身是坏实践,2.0 不会救它。
- 开关:
read_ahead_depth控制下载池可以领先 worker 多少个 row group,默认-1即自动(按线程数推算),等于默认开启;设成0退回 1.5 的行为。查询侧不用改一行 SQL。 - 递归 CTE 的重写:1.5.5 每一轮都重新扫一遍全表找下一层,八层组织树就是八次全表读,上万层的 git 历史就是上万次全表读。2.0 只读一次表、在 parent 列上建一次查找结构,每轮只查找刚找到的那几行,代价从「轮数 × 表大小」变成「实际触碰的行数」。作者生成的 2 万提交仓库上,回溯祖先链 1.5.5 耗时在 1.8 到 16 秒之间波动,2.0 alpha 每次都是 0.10 秒。
- 什么时候能看到提升:层级深的数据——git 历史、数据血缘、回复串、完整 BOM——才吃得到这波红利。组织树这种只有七八层的浅结构几乎看不出差别。建模上仍建议把层级存成一张 parent/child 整数 ID 表,递归要携带 depth 或 cost 这类值时用
USING KEY。 - VARIANT 的 shredding:写 row group 时,DuckDB 会检查 JSON 列,把「多数行都出现且值类型稳定」的字段抽成真正的列,罕见字段和类型会在数字与文本之间跳的字段留在二进制 remainder 里。结果是 JSON 的稳定部分按普通表的方式存,只有杂乱部分才是 blob。作者的实测是存储降到约三分之一,字段查询跑得像真列。
- VARIANT 目前的短板:把 VARIANT 的 list 转成
VARCHAR[]在这个 alpha 里要多花约 2 秒,比走 JSON 路径更慢。字段访问是 shredding 当前真正兑现收益的地方,list 还没跟上。建模的老规矩依旧成立:每个查询都要碰的字段值得提升成真列,两句话就能做(ALTER TABLE加列 +UPDATE回填),长尾留在 VARIANT 里。 - 发布记录与 commit log 里的其他条目:触发器(用 transition tables 把变更前后的行写进历史表,不必每个写表工具都记得写一遍);嵌套 schema(
CREATE SCHEMA finance.reports);CTE 里跑 DML(DELETE ... RETURNING放进WITH再INSERT出去,即原子搬行);SET dialect_compatibility_mode = 'spark'用于从 Spark SQL 迁移部分管线;SET external_file_cache_spill = true让被淘汰的远程文件块溢写到临时目录而非重新下载——300 MB 内存限制下,854 MB Parquet 的第二次读取从 23.9 秒降到 0.35 秒;read_json现在把带偏移的 ISO-8601 识别为TIMESTAMPTZ而不是静默丢掉偏移;CREATE SECRET ... IN CONNECTION把密钥作用域收窄到单个连接;CLI 增加了 SQL 格式化器、可查询的历史与.manual;客户端-服务端协议 Quack 随这次发布升到 1.0。
行业影响
异步 I/O 这组数字的意义不在倍数,而在它对用户是隐形的。过去要把对象存储上的查询跑快,选项不外乎把数据搬近、加缓存层、或者接受慢;现在引擎把下载和解码解耦,同样的 SQL、同样的文件、同样的机器就能快一倍多。对把湖建在 S3 或 COS 上的团队,这等于把一部分「数据布局优化」的收益提前发放了——但也没全部发放,小文件那一栏的数字就是提醒。
递归 CTE 的重写改变了另一条边界。血缘、依赖图、git 式历史这类查询过去常被推给图数据库,理由不是图数据库更合适,而是关系引擎每轮重扫全表撑不住深度。改成「读一次 + 建一次查找」之后,这类查询回到普通 SQL 能覆盖的范围,少了一个要独立运维的组件。VARIANT 的 shredding 也是同类动作:半结构化数据不必再在「全存成 JSON 文本」与「提前拆成几十列」之间二选一,引擎替你按实际分布拆。
相关链接
- Why DuckDB 2.0 is faster(MotherDuck,2026-09-10)
- Try DuckDB v2.0-alpha(DuckDB 官方,2026-09-02)
- How DuckDB Runs Recursive CTEs Faster(DuckDB 官方,2026-08-25)
- DuckDB v2.0: Your Database Deserves a Better Parser(DuckDB 官方,2026-08-20)
Daft 0.7.25:Iceberg 静态分区覆写、WebDataset 读取器与一批正确性修补
事件概述
Daft 在 9 月 11 日发布 v0.7.25(GitHub 记录的发布时间为 2026-09-11 23:48 UTC),距上一个版本 v0.7.24 约四周。这是一个补丁号,但内容与常见的补丁版本不同:四个新特性、十一个修复、一处性能优化、一处重构,其中 Iceberg 写入侧的 overwrite_filter 与全新的 WebDataset 读取器都属实质增量。另有 8 位首次贡献者进入这个版本。
Daft 的定位一直是「面向多模态与 AI 负载的分布式 DataFrame」,与 Spark、Polars、Ray Data 在同一片区域竞争。这个版本的改动方向清楚:把多模态数据格式的入口补齐,并把湖表写入的语义补到能与 Iceberg 生态对齐的程度。
技术解析
- Iceberg 静态分区覆写:新增
overwrite_filter(PR #7419),允许在覆写时按谓词限定范围,静态分区场景不必再重写整表。此前 Daft 的 Iceberg 写入在覆写语义上选项有限,遇到「只重刷某几个分区」的需求只能绕道。 - WebDataset 读取器:新增原生 WebDataset reader(PR #7493)。WebDataset 是 PyTorch 生态里常见的分片 tar 打包格式,用于大规模图像/音视频训练数据的顺序读取。写入引擎原生支持后,多模态训练集不必先解包成散文件再被扫一遍。
- lerobot 数据集布局:支持 v2.0 与 v2.1 两种布局(PR #7381)。LeRobot 是 Hugging Face 的机器人学习数据集格式,版本迭代后目录结构有变化,这个特性让 Daft 能直接读两个版本的产物。
- 优化器:limit 现在可以下推过「保行的 join 侧」(PR #7439)。对 join 后取前 N 条的查询,若某一侧保证不改变行数,limit 就能推到那一侧提前截断,减少参与 join 的数据量。
- Parquet field ID 的行为收紧:此前 Parquet 文件缺少 field ID 时,Daft 会把相关列置为 null;现在改为直接报错(PR #7446)。这是把静默的数据丢失改成显式失败,对依赖 field ID 做列映射的下游(尤其是 Iceberg)是必要的。
- UDF actor 泄漏:修复未被调度的 UDF actor 不会被清理的问题(PR #7346)。长跑的分布式作业里,这类泄漏会慢慢吃掉资源。
- SQL 字面量转义:修复 SQL 字面量渲染时单引号未转义的问题(PR #7269)。这是把表达式下推到 SQL 引擎时的典型注入类缺陷。
- 其他修复:
coalesce()的参数校验此前不可达(PR #7404);regexp_replace的替换串此前会吞掉反斜杠(PR #7472);Gravitino Iceberg REST 目录需要显式声明 noop auth(PR #7417);分布式执行中 input 处于 pending 状态时后台错误不浮现(PR #7396);from_postgres的 extensions 参数存在共享可变默认值(PR #7426)。 - 性能:取文件大小不再打开文件(PR #7481)。列裁剪与文件级的代价估算都要读
file_size,这类元数据操作在宽目录上会被放大。 - 重构:分布式 shuffle 的后端配置统一到
daft-local-plan的ShuffleBackend(PR #7402),把此前分散的多套配置收敛成一处。
行业影响
把 overwrite_filter 和 WebDataset reader 放在一起看,Daft 在补的是两类不同的入口:一个是湖表写入的语义完整性,一个是多模态数据格式的覆盖面。这两块恰好是它在与 Spark 竞争时最容易被问到的地方——Spark 有成熟的动态/静态分区覆写语义,也有庞大的数据源生态;多模态侧则更接近 Ray Data 的地盘。
Parquet field ID 那条修复值得单独拎出来。把「静默置 null」改成「报错」是这类引擎的成熟标志:数据不正确比作业失败更贵,尤其在 Iceberg 这类靠 field ID 做 schema 演进的格式上,一列悄悄变成 null 可能要到几层下游才被发现。缺点是升级会让原本能跑(但结果错误)的作业直接失败,属于需要提前安排的破坏性变更。
相关链接
- Daft v0.7.25 Release Notes
- feat(iceberg): add overwrite_filter for static partition overwrite(PR #7419)
- feat(io): add WebDataset reader(PR #7493)
- feat(lerobot): support v2.0/v2.1 dataset layouts(PR #7381)
- fix(parquet): error instead of nulling columns when field ids are absent(PR #7446)
- Daft 官网
Lakeflow Connect 收编营销数据源:16 个托管连接器与开箱即用的广告报表
事件概述
Databricks 在 9 月 11 日发布《Unify your marketing data with Lakeflow Connect》,作者是 Sonia Bendre 与 Giselle Goicochea。这是 Lakeflow Connect 新系列博客的第一篇,主题是 Customer 360——作者称它是企业里最碎片化的数据栈。
文章给出的核心变化是连接器覆盖面的扩展:16 个 SaaS 源有了原生的全托管连接器,数据落成 Unity Catalog 里的受管表,用户不需要准备、管理或扩缩任何基础设施。本专栏 Vol.60 报道过 Lakeflow Connect 在 9 月 4 日把托管流式摄取扩到 Kafka 与 RabbitMQ,那次解决的是消息中间件这一侧;这次补的是应用侧的 SaaS 源,两者是同一条产品线的不同方向。
技术解析
- 16 个连接器按客户旅程分四段:获客(Google Analytics、Meta Ads、TikTok Ads、Reddit Ads、LinkedIn Ads、Google Ads、Google Search Console)、互动(Salesforce Marketing Cloud、SendGrid、Marketo)、关系(Salesforce、HubSpot、Dynamics 365)、体验(Zendesk Support、Amplitude、Pendo)。
- 广告报表开箱即用:Google Ads、Meta Ads、TikTok Ads、Reddit Ads、LinkedIn Ads 五个连接器直接产出已聚合的报表表,含 spend、impressions、clicks、conversions 四类指标。每个报表落成独立的受管 Delta 表并增量刷新。
- 预置与自定义两类报表:预置报表覆盖常见需求,无需配置,例如 TikTok Ads 连接器的
campaign_report_daily(按日 campaign 表现)与campaign_age_gender_report(按受众拆分)。自定义报表允许分析人员指定层级、维度、拆分方式与指标,例如 Meta Ads 连接器可设置归因窗口与 timeframe,让数据与自己的度量口径对齐。 - 托管认证:Meta Ads、Google Ads、TikTok Ads 三个连接器支持托管认证流程,配置简化为一次 OAuth 登录。
- 多账户隔离:每个广告账户的表可以路由到独立的目标 schema。目前只能通过 API 配置,UI 支持即将推出。
- Ad-Genie 加速器:把摄取到的 bronze 表加工成 silver 与 gold 表,驱动一套开箱即用的 AI/BI 仪表盘与 Genie 会话代理,底层由 Unity Catalog 里的受管 metric views 提供口径。官方称从原始广告数据到受管 Customer 360 和自然语言代理只需三步。
- 与 CI/CD 的配合:连接器支持 Declarative Automation Bundles,可以纳入既有的 CI/CD 流程。EcoVadis 的数据工程负责人提到这是他们选型时能直接接入现有流程的原因。
- 客户侧的两个数字:iManage 的数据工程经理称,五年前在 Synapse 上自建 Salesforce 连接器花了数月,这次用 Lakeflow Connect 一个下午完成,他们有 500 到 700 个自定义对象且新需求不断。文章未给出其他量化指标,其余客户引述(EcoVadis、The Krazy Coupon Lady)为定性评价。
- 路线图:Adobe Campaign 与 Adobe Analytics 在支持计划中。
行业影响
营销数据栈的碎片化是个老问题,过去的标准答案是 Fivetran、Airbyte 这类独立 ETL 产品,或者自建。托管连接器进入计算平台之后,竞争维度从「谁的连接器多」变成了「连接器落在哪一层」——落在平台内部意味着摄取产物天然带有同一套治理、血缘与权限,不必再跨系统同步一次元数据。
代价是灵活性与覆盖面。自定义报表目前需要分析人员自己指定维度与指标,等于把一部分建模工作留在了配置里;按广告账户路由 schema 只有 API 路径,UI 还没跟上;连接器清单由厂商按客户需求排序推进,长尾来源仍然要自己写。对已经投了 Fivetran 或 Airbyte 的团队,这笔账会落在「少维护一套系统」与「失去一部分数据源自由度」之间。
相关链接
Databricks 9 月平台发布记录:外来 Iceberg 表进入 OpenSharing,自动 CDF 与 ABAC DENY 推进
事件概述
Databricks 的平台发布记录在 9 月更新了一批条目,其中共享与治理相关的几项值得单独拎出来:通过 OpenSharing 共享外来 Iceberg 表转为 GA,外来 schema 与外来表的共享同样转为 GA,自动变更数据馈送(automatic change data feed)转为 GA,ABAC DENY 策略进入 Beta,Unity Catalog 的外部密钥进入 Beta,另有 time_bucket SQL 函数与 Zerobus Ingest 写入默认存储的公测。
需要说明的是,这份发布记录按月归档,没有给出逐条的具体日期,因此只能定位到 9 月。下面涉及的限制条款来自对应的产品文档,而非发布记录本身。
技术解析
- 共享对象的扩展:OpenSharing 此前主要服务于 Delta 与 Databricks 管理的表;这次把外来 Iceberg 表、外来 schema 与外来表一并纳入,形成「数据留在外面、共享发生在 Unity Catalog 这一层」的形态。外来 Iceberg 表指的是通过 Lakehouse Federation 从外部 Iceberg 目录联邦进来的表。
- 账户级前置条件:共享外来 Iceberg 表需要先在账户层面启用 Lakehouse Federation Sharing 预览。
- 新鲜度需要主动维护:文档明确要求定期刷新外来 Iceberg 表,任何
SELECT查询或REFRESH TABLE命令都会刷新表元数据。官方建议配置定时作业让它与远端 Iceberg 源保持同步——共享出去的是最近一次刷新看到的快照,不是实时代理。 - 面向非 Iceberg 客户端的路径不同:把外来 Iceberg 表共享给不使用 Iceberg 客户端的开放接收方时,必须使用默认存储,共享数据会先用提供方的计算与存储做一次过滤和物化,会产生额外费用。走 Iceberg 客户端的接收方则不走这条路径。
- 外来表/外来 schema 共享的成本特征:文档指出系统会完整物化查询结果再返回给接收方,与查询条件无关。官方建议把典型查询结果控制在 10 GB 以内,用即席探索性查询而非频繁全量拉取;用 cloud-token 共享时,建议改共享建在外来表之上的物化视图,成本与性能都更好。
- 自动变更数据馈送 GA:CDF 过去需要在表上显式启用,转为自动之后,增量消费链路少了一个容易忘的配置项。这对把湖表当流式源用的架构影响最直接。
- ABAC DENY 策略进入 Beta:与 9 月 10 日那篇跨引擎治理文章里的 ABAC 推进方向一致(本专栏 Vol.63 已记录 catalog labels 与 read restrictions)。DENY 语义补齐之后,策略不再只能表述「允许什么」。
- 外部密钥进入 Beta:Unity Catalog 开始管理外部密钥,把凭据从作业代码里挪进目录,与近几期看到的「把判断下沉成可声明对象」是同一条线。
行业影响
共享协议的竞争点已经从「能不能共享」移到「共享什么」。OpenSharing 覆盖外来 Iceberg 表之后,Unity Catalog 可以只做共享与治理层,数据实体留在原来的目录里——这对跨组织、跨云协作是实质性的简化,因为不必再为了共享而先复制或转换一份。
限制条款同样要读。物化查询结果会带来成本与配额上的现实约束(10 GB 那条建议),外来表需要定时刷新意味着「零复制」不等于「零延迟」,接收方看到的仍是某个时间点的快照。对已经把 Iceberg 目录联邦起来的团队,这些条款决定了架构能走到哪一步:高频、大结果集的共享仍适合走物化视图或常规表;低频、探索性的跨组织查询才是外来表共享的主场。
相关链接
- Databricks platform release notes(AWS,September 2026)
- Create and manage shares for OpenSharing(含外来 Iceberg 表共享的要求与限制)
编者评
把这四条排在一起,共同点是都在削减重复次数。DuckDB 2.0 把表从「每轮读一次」改成「只读一次」,把 JSON 的稳定字段从「每行存一遍」改成「抽出来存一遍」;Daft 的 overwrite_filter 让分区覆写不必重写整表,取文件大小不再打开文件;Lakeflow Connect 把 N 个源的 N 套 API 集成收成一份托管连接器,广告报表从每个团队自己聚合变成连接器预置;OpenSharing 让共享不必先复制一份数据,自动 CDF 让增量消费不必记得开一个开关。
有意思的是四处都留下了没被削掉的那一次,而且形态相似——都是「引擎或平台替你做了,但某些条件下它做不了,或者做了要额外付钱」。异步 I/O 对小文件无效,因为瓶颈是每文件两次往返而非带宽;VARIANT 的 list 转型在这个 alpha 里更慢,shredding 目前只在字段访问上兑现;Parquet field ID 缺失这条从静默置 null 改成报错,等于把一次「错误的免费」换成一次「正确的失败」;外来表共享省掉了复制,却要定期刷新,还可能在面向非 Iceberg 客户端时额外物化一次。
这提示了一种读这类新闻的实用顺序:先看它省掉了哪一次重复,再看那一次重复在什么条件下会重新出现。本期四条里,重复重新出现的条件分别是文件粒度、数据类型、输入质量与共享路径——都是能在设计阶段就判断的东西,而不是上线之后才撞见的意外。