datainfra前沿动态 · Vol.89

DuckDB 给 CLI 加了一层专为编码 Agent 设计的输出契约;Flink CDC 3.7.0 把模型调用搬进管道并给已存在的目标表划出三种 schema 处置模式;dbt 换掉 pg_* 元数据打通 Redshift 跨库写;Google 把 Lakehouse 目录铺到 22 个区域并把 15 项以上服务接进编码 Agent

本期聚焦数据栈开始为非人类调用方重写契约:终端输出为模型重做,管道写入为不归自己所有的表划边界,目录与身份为跨区域、跨集群、跨 IDE 的读取方补接口。

DataInfra DuckDB Flink CDC dbt Redshift Data Sharing Google Cloud Iceberg Lakehouse MCP Agent

本期四条里有三条在处理同一件事:调用方不再是人。DuckDB 在 v2.0 的 CLI 里加了一层 agent 模式,把「结果被截断」「查询出错了」这类此前靠人眼扫一眼 footer 才能发现的事实,改成机器上可判定的标记、计数与哈希;Flink CDC 3.7.0 一边把模型调用塞进 YAML Transform,一边给已经存在的目标表划出 CHECK、TRY_EXPAND、EXPAND 三种处置模式;Google 用 MCP 把 15 个以上的数据服务接进 VS Code、Cursor、Claude Code 与 Codex,并把 Lakehouse 目录铺到 22 个区域。第四条是 dbt 把 Redshift 的跨库写从「必须落成表、必须同集群」的窄口径放开,代价是元数据查询从 Postgres 的 pg_* 换成 Redshift 的 SVV_*。

DuckDB 给 CLI 加了一层专为编码 Agent 设计的输出契约

事件概述

DuckDB 在 10 月 9 日的博客里介绍了 v2.0 CLI 新增的 agent 模式。起因很直接:今天大量 duckdb -c "..." 的调用不是坐在终端前的人发起的,而是 Claude Code、Codex、Cursor、Gemini CLI、GitHub Copilot 这类编码 Agent 通过管道抓取 stdout 再喂给模型。默认渲染器是为「有终端、有翻页器、能自己要求更多输出」的人设计的:列被填充对齐,结果被画进方框,大结果只显示首尾各 20 行并在 footer 里写一行 (40 shown)。模型没有终端,不能要求更多,还要为每一个填充字符付费,且很容易扫过那行 footer,然后基于自己从未看到的数据下结论。

Agent 模式针对这个读者改了默认输出:结果打印成不带对齐填充的 Markdown 表格;超过 1000 行或 10000 字节的结果改成首尾各 20 行加一行显式省略标记;达到上限后只计数和哈希,再多 10 万行就停掉查询并把计数标成下界;错误以 JSON 写到 stderr;planner 预计读取超过 100 万行时先往 stderr 打一行成本预估。开启条件是三条都成立:某个 Agent 环境变量已设置、stdout 不是终端、命令行没有指定输出格式。

技术解析

  • 检测与开关:shell 依次检查 AI_AGENT、AGENT、CLAUDECODE、CODEX_CI、CODEX_SANDBOX、CODEX_THREAD_ID、CURSOR_AGENT、GEMINI_CLI、COPILOT_AGENT、COPILOT_CLI、COPILOT_AGENT_SESSION_ID。三条都成立才开启;传了 -csv、-json 或 -markdown 就视为你明确要那个格式,agent 模式让路。-agent 与 -no-agent 两个标志绕过检测,.show 会报告当前是否开启以及识别到哪个 Agent。未被识别的 Agent 在管道里跑失败时,stderr 会打一行 hint 告诉它这个模式的存在。
  • 体积:Markdown 表格把列类型放进表头单元格,官方给的范围是比方框输出小 25% 到 65%,宽表省得最多。1000 行与 10000 字节以内完整打印,超出部分变成首尾各 20 行,中间一行 … 4960 rows omitted …,footer 写明 first 20 and last 20 of 5000 rows (.maxbytes 0 for all), hash 7389c2f5ff3cefb6。.maxrows 与 .maxbytes 可调,-1 或 0 表示不限。单元格超过 500 字符会截断并标出 …(+4500 chars)。
  • 早停与哈希:达到上限后剩余行只做计数与哈希;再走 10 万行就停掉查询,计数标为下界。FROM range(1_000_000_000) 在 30 毫秒内返回,footer 是 first 20 of at least 102400 rows (query stopped early; .maxrows -1 for all)。哈希覆盖超过上限的那些行,与行序无关,且能区分 NULL 与字符串 NULL。查询被早停时不打哈希,因为它覆盖不了完整结果。
  • 错误与计划:错误走已有的 errors_as_json 设置,shell 自身的错误(比如未知的点命令)也包进同一结构。shell 去掉 candidates 字段,官方的理由是一条「no matching function」错误带上它会重 2.7 kB。EXPLAIN 默认换成 compact 格式,一个算子一行、按深度缩进,估计值、实际行数与耗时放在括号里;EXPLAIN ANALYZE 开头多一行 QUERY (time=0.0012s, read=1.2 MB)。这个格式在 agent 模式之外也能用 EXPLAIN (FORMAT compact) 显式调用。
  • 代价提示:planner 预计读取不少于 100 万行时,执行前先往 stderr 打 estimate: ~7501215 rows read (lineitem ~6001215, orders ~1500000), ~4 rows returned;长查询运行期间每 5 秒打一行 progress: 42% (elapsed 12.0s, remaining ~16.5s)。.tables 改成一行一张表并带上近似行数与列定义,例如 memory.main.t1 (table, ~15 rows): a INTEGER PK, b VARCHAR。
  • 实测口径:团队让 Claude Code 用自然语言回答 TPC-H SF100 的 22 个问题,agent 模式与 -no-agent 各跑三遍,132 次运行答案全部正确。模型读到的 DuckDB 输出从 123.6k token 降到 50.8k token,降幅 59%。官方还说明了两件事:省下的 token 只占总输入约 0.5%,因为每一轮都要重读远大于查询输出的 system prompt;agent 模式那组的轮次略多,237 轮对 224 轮。
  • 版本状态(重要):agent 模式随 DuckDB v2.0 发布。截至本期,PyPI 上 duckdb 的最新稳定版仍是 1.5.6,2.0 只有 dev 构建(最新为 2.0.0.dev2610011535,2026-10-01)。也就是说这套输出契约还没落到稳定版上,想用得等 2.0 正式发布或切到 dev 包。

行业影响

这件事的分量不在省下的 token,而在它承认了一件事:命令行工具的输出格式是一种接口,而这种接口此前只为人设计过。方框渲染、首尾截取样、文本化错误,全都是靠人的常识兜住的信息缺口 —— 人看到省略号知道缺行,模型不知道。DuckDB 的解法不是给模型更多数据,而是把「缺了多少」「为什么缺」「怎么拿全」这三条写进 footer,并在拿不全时用哈希提供一个可比较的指纹。

另一个信号是工具开始为「调用方不可交互」做设计。早停、成本预估、进度行,这三件事解决的都是同一个问题:Agent 没有办法中途改主意,除非工具先把代价告诉它。这类改造会被复制的余地不小,任何被 Agent 高频调用的 CLI 迟早都要过一遍。

相关链接


事件概述

Apache Flink 社区在 10 月 10 日发布 Flink CDC 3.7.0(作者 Xiqian Yu)。这一版的主线是「AI 驱动且可扩展的 Transform」:引入可插拔的 AI 模型客户端 API 与一个 OpenAI 兼容的客户端,让文本生成与 embedding 能直接写进 YAML Transform 表达式;配套一组内置 AI 函数,覆盖补全、分类、翻译、摘要、情感分析、信息抽取、脱敏、文本向量化与图像理解,并支持按记录动态选模型。为了让这类 I/O 密集的表达式不至于拖垮管道,这一版加了实验性的有序异步执行,在保住数据与 schema 事件顺序的前提下提高吞吐。

另一半改动在「写」。Flink CDC 往一张已经存在的目标表写数据时,对目标表 schema 的态度此前是隐式的。3.7.0 给 Paimon 与 Fluss sink 加了已有表的 schema 校验与扩张,模式显式化为三个枚举:CHECK 只校验、TRY_EXPAND 尝试扩张、EXPAND 直接扩张,扩张范围限定在写数据前安全地新增或放宽非键列。

技术解析

  • AI 模型接入:可插拔模型客户端 API(FLINK-39568、FLINK-40411)加 OpenAI 兼容客户端,作用于 YAML Transform 表达式;内置 AI 函数(FLINK-40416、FLINK-40513、FLINK-40572)覆盖九类任务,支持逐条记录动态选模型。有序异步执行(FLINK-40552)目前是实验特性,官方给的目标场景是模型调用这类 I/O 密集表达式。
  • 写入侧 schema 处置:FLINK-40647 给 Paimon 与 Fluss sink 加了 CHECK、TRY_EXPAND、EXPAND 三种模式,在写数据前校验已有目标表,并安全地新增或放宽非键列。键列不在扩张范围内。
  • 分区与路由:FLINK-39777 新增可配置的 sink 分区策略(sink 自定、主键、表 ID 三种);FLINK-39696 改用 source 分区分发分布式 flush 事件,修的是非哈希或自定义分区策略下的正确性问题;FLINK-40148 修正源表名含多位数后缀时的路由替换,让替换消费完整源表 ID,不再把未匹配的后缀漏进 sink 表名。
  • 配置与状态:FLINK-36581 允许在 Pipeline YAML 里用 pipeline.flink-conf 写 Flink 配置,CLI 参数优先级最高;FLINK-40656 修正从 checkpoint 恢复时 schema coordinator 状态的重置。
  • 新 source:SQL Server Pipeline source(FLINK-39252)支持增量快照读、schema 变更同步、元数据列、多种启动模式,以及从 checkpoint 或 savepoint 恢复后扫描新增表;Apache Fluss Pipeline source(FLINK-39722)支持主键表与日志表、快照与日志读取、周期性表发现,FLINK-40575 支持动态退订与重订,Fluss 依赖升到 1.0.0,Fluss sink 增加 forward-shuffle(FLINK-40331、FLINK-40690)。
  • 各 sink 的修与补:Paimon 支持 postpone bucket 模式与 BLOB 字段(FLINK-37731、FLINK-39567),依赖升到 2.0.0;Hudi sink 支持 Hive 同步(FLINK-40159);Iceberg sink 支持用 hadoop.conf.* 前缀透传 Hadoop 配置(FLINK-39342),并修掉 schema 变更在一个 checkpoint 内拆分写入或更新改变分区值时的重复记录(FLINK-38450、FLINK-40640);Kafka 修 Debezium JSON 在列含默认值时的序列化(FLINK-39757);StarRocks 修 utf8mb4 下的 CHAR 与 VARCHAR 映射,以及生成 DDL 里的引号转义;Oracle 支持不改类型只改列可空性,并修正精度不低于 19 的 NUMBER(p, 0) 映射;MaxCompute sink 修分区处理。
  • 增量源框架的内存账:FLINK-39732 引入 ObjectIdDiscoverer SPI 做源表发现,默认提供 JDBC 实现;FLINK-40623 在表切分完成后释放 chunk splitter 的 JDBC 连接;FLINK-39775、FLINK-40697、FLINK-40732 在进入流阶段后释放已完成的快照分片元数据(覆盖 MySQL、基于增量快照的源与 MongoDB),官方明确的收益是降低长跑作业的 coordinator 状态与内存占用;FLINK-39621 修 binlog 回填期间卡住的问题。

行业影响

把模型调用放进 CDC 管道,等于承认「清洗与富化」这一层长期存在的 CPU 密集型假设已经不成立。当一条 transform 需要一次网络往返时,管道的瓶颈从算子转移到外部服务的延迟与限流,Flink CDC 给出的应对是先做一个保序的异步执行,而不是让用户自己在外面套一层批处理。这个设计能不能扛住真实流量,取决于有序异步执行的成熟度,它目前标注为实验特性。

另一处改动的意义更长远。Flink CDC 此前默认自己拥有目标表,schema 由它推导、由它演进。CHECK、TRY_EXPAND、EXPAND 三个枚举把它摆到了「我只是众多写入方之一」的位置上 —— 目标表由别的团队建、由别的管道维护,schema 演进变成一次需要声明权限的操作。这个转向和 Iceberg、Delta 这几年在目录层做的事是同一个方向:写入方要显式声明它对目标拥有什么程度的处置权。

相关链接


dbt 换掉 pg_* 元数据,把 Redshift 跨库写与环境隔离一起打通

事件概述

dbt Labs 在 10 月 9 日(作者 Stephen Robb)宣布 dbt-redshift 原生支持 Amazon Redshift data sharing 的读写。Redshift data sharing 本身允许把活数据跨集群、跨账号、跨区域共享出去而不复制一分钱数据:生产方把库对象暴露给消费方,消费方像查本地表一样查,读到的是生产方提交后立即可见的、事务一致的数据。dbt 此前用不上这个能力。模型只能在很窄的条件下引用外部数据库里的 source,需要 RA3 或 serverless 节点,需要 ra3_node: true 这个特殊 profile 开关,且任何引用 datashared source 的模型都必须物化成表 —— 视图不行,跨项目引用不行,跨集群的高级 CI 也不行。

这一版的核心是新增一个 profile 凭据 datasharing: true。dbt 往一个非当前连接的数据库写之前要先 introspect 该库,默认是查 PostgreSQL 的 pg_tables、pg_views 与 information_schema,这些只反映当前连接库内的对象,于是跨库写会失败并报 Cannot write to a different database inside a transaction when USEd db was not set before the transaction began。打开这个开关后,适配器的元数据查询切到 Redshift 原生的 SVV_* 系统视图与 SHOW API,这些是跨库可见的。

技术解析

  • 三步配置:在 Redshift 里 CREATE DATABASE dev_analytics;模型加 {{ config(materialized='table', database='dev_analytics') }};在 dbt platform 的 Environment → Extended attributes 里加 datasharing: true(本地写在 profiles.yml)。dbt platform 上无需改代码。
  • 状态与前置:datasharing: true 在 dbt platform 的 Latest 发布轨道上处于 Beta,Compatible 与 Extended 轨道还没有;本地需要 dbt-redshift v1.11+。节点要求是 RA3、RG 或 Serverless,DC2 不支持 data sharing。
  • 它不解决权限:官方明确写了,这个开关只打通元数据路径与事务上下文,不授予数据库权限。连接用的数据库用户仍需要有目标库的 CREATE 权限,否则报的是权限错误。
  • 与 defer 配合:两件事发生在同一次 dbt run 里 —— 上游模型通过跨账号 datashare 延迟解析到生产数据,当前模型物化到 dev 目标库。这让 dev 环境可以做到真隔离(独立集群、独立数据库、独立 AWS 账号),又不必复制生产数据。
  • 解锁的三类用法:dbt Mesh 的跨项目 ref() 可以跨越不同的 Redshift 数仓与数据库;高级 CI 可以把 CI 环境放在专用集群上,只通过 datashare 读生产的共享源数据;工作负载隔离可以把重转换任务从跑看板的集群上摘走,全部在 dbt 项目配置里完成。
  • 顺带的性能账:即便不用 data sharing,这一版也更快了。从 pg_* 迁到 SVV_* 与 SHOW 不只是为了跨库可见性,pg_* 这套继承来的视图不是为 Redshift 架构设计的,在大规模、高并发下每次 dbt run 都会叠加可观的元数据查询开销,官方的说法是每个查询数秒级的开销乘以大量模型。SVV_* 与 SHOW 的结果不随并发或集群规模变化。
  • 限制(AWS 侧):消费方集群上不能在 datashared 表之上直接建普通视图,这是 AWS 层面的限制。绕法是先把 datashared 数据物化成表或增量模型,再在其上建视图;late-binding view 与物化视图可以从生产方共享出来。跨 datashare 的写操作(INSERT、UPDATE、DELETE)在 AWS 侧另有 SQL 约束。

行业影响

这条改动说明了一件容易被忽略的事:很多「平台不支持」其实是元数据查询不支持。dbt 跨库写失败的表层原因是事务上下文,根因是适配器在用一套只看见当前库的目录视图。换成 SVV_* 之后,跨库写、跨账号 defer、跨项目 ref 三件事一起解锁,成本只有一个布尔开关。

把视角拉远一点,dbt 与 Flink CDC 这一期的改动落在同一条线上:两者都在处理「写入方不拥有写入目标」的场景,且都选择把它写成一个显式声明 —— 一个是 datasharing: true,一个是 CHECK、TRY_EXPAND、EXPAND 三个枚举。过去这类关系靠部署文档和口头约定维持,现在被推进了配置文件。

相关链接


Google 把 Lakehouse 目录铺到 22 个区域,并把 15 项以上数据服务接进编码 Agent

事件概述

Google Cloud 在 10 月 10 日更新了数据云的周更汇总,覆盖 10 月 5 日到 9 日这一周。与数据基建最直接相关的两条是目录与身份的扩张:Lakehouse runtime catalog 的区域端点已在美洲、欧洲、亚太与中东的 22 个 Google Cloud 区域上线,Apache Iceberg REST catalog 端点与 Apache Hive catalog 端点并列提供,官方给出的理由是满足严格的数据驻留与主权要求;Apache Iceberg 表的灵活列名 GA,默认支持含空格、连字符、Unicode 字符的列名查询,外部表与托管表都覆盖。

其余两条指向 Agent。Data Agent Kit GA,提供一组免费的 MCP 工具与 Google 自己写的 agent skills,把 15 个以上的 Google Data Cloud 服务接到 VS Code、Antigravity、Cursor、Claude Code 与 Codex,开发者可以在 IDE 或 CLI 里用自然语言查 schema、写查询、搭端到端管道。Spanner Omni GA,把 Spanner 的分布式 SQL、图、向量与键值能力带到本地数据中心、其他公有云(通过 Kubernetes 或 VM)与开发机,混合与多云下 API 与查询引擎保持一致;同一周 Spanner 还移除了 DML 事务的累积 mutation 限制。

技术解析

  • 目录与主权:区域端点在 22 个区域落地,Iceberg REST 与 Hive 两类端点并列提供。Hive 端点的加入意味着还没有迁到 Iceberg REST 的存量集群也能挂上来。
  • Iceberg 列名 GA:含空格、连字符、Unicode 的列名在 Iceberg 外部表与托管表上默认可查,不需要额外开关。
  • BigQuery 一侧:新增六个内置的增强分析表值函数(TVF),自动做指标诊断、趋势分析与模式发现,并可作为 AI agent 的 skills 调用;TabFM 把表格基础模型能力引入预测分析;identity columns 自动生成序列代理键。
  • Dataflow:新增 Pause/Resume 作业控制,并支持 NVIDIA RTX PRO 6000 Blackwell GPU,官方给的场景是大规模 AI 负载下的高吞吐流与批管道。
  • AlloyDB 与 Cloud SQL:面向 Agent 的 PostgreSQL 架构(实时数据访问与工作负载隔离);原生 BM25 混合排序进入 Preview,关键词检索与向量检索在 PostgreSQL 内直接结合,不必再维护外部搜索引擎;AlloyDB Omni RPM Orchestrator GA。
  • Spark 可用性:Google 给出 Yahoo 在 Managed Service for Apache Spark 上使用 flexible VMs 的结果,配置失败减少 85%。配套文章讲如何用 flexible VMs 缓解算力库存不足。
  • 缓存层:Memorystore for Valkey 9.1 提供最高 3 倍 QPS 与微秒级缓存延迟,官方把它定位在高吞吐应用与实时 Agent 状态管理上。

行业影响

Google 这一周的发布里,目录那一半是「把已经存在的东西铺开」,Agent 那一半是「给新的读取方补接口」。前者说明 Lakehouse catalog 的竞争已经从功能转到覆盖:22 个区域、两类端点、列名兼容,这些都不是新能力,却是采购与合规环节真正会问的问题。后者说明厂商已经默认数据的读取方会是一个坐在 IDE 里的模型,MCP 工具与 agent skills 是给它的 SDK。

把它和本期第一条放在一起看会更清楚:DuckDB 在改单机 CLI 的输出契约,Google 在改云服务对 Agent 的暴露方式,两边都在为同一类新消费者重做接口层。区别只在于 DuckDB 解决的是「别让模型读到假数据」,Google 解决的是「让模型够得着数据」。

相关链接


编者评

本期四条可以读成同一个动作的四个切面:把此前由人的常识、部署文档与口头约定兜住的东西,改成显式、可枚举、可校验的开关。DuckDB 面对的是「模型不知道结果被截断」,给出的答案是机器可读的 footer、哈希与早停,而不是给模型更多数据;Flink CDC 面对的是「目标表不归我管」,给出的答案是 CHECK、TRY_EXPAND、EXPAND 三个枚举;dbt 面对的是「跨库写为什么失败」,答案是元数据视图换成 SVV_* 加上一个 datasharing: true;Google 面对的是「谁在查我的数据」,答案是 22 个区域的区域端点与接进 IDE 的 MCP 工具。

四处改动的共同点是它们都没有消灭原有的不确定性,只是把不确定性搬到了一个能被看见、能被声明的位置。DuckDB 不保证模型拿到全量,它保证模型知道自己没拿到全量;Flink CDC 不保证目标表 schema 一定能改,它保证改动范围被写成一个枚举;dbt 不保证你有权限,它明确区分元数据路径与权限两件事;Google 不保证跨云一致,它把驻留边界做成可配置项。这类显式化的改造在短期内会增加配置项的数量,长期看是把隐性知识从人身上转移到系统里。

还有两条本期没有单独成篇的线索值得记一笔。Apache Arrow 26.0.0 在 10 月 9 日发布,403 个提交、108 位贡献者,C++ 侧把 RapidJSON 全线换成 simdjson,覆盖 tensor 扩展类型、OpaqueType、FlightSQL ODBC、Dataset 与 JSON chunker,并给 Parquet 读取加了 schema 嵌套深度限制。LanceDB 在 10 月 9 日连发 v0.41.0-beta.2 与 beta.3,改动集中在远端 API 的实体名校验统一、Flight DoExchange 上的 SQL 查询参数绑定,以及 JSON 字段上的全文索引。

中文源方面,本期未再投入轮次抓取阿里云与火山引擎的公开更新页,这是连续第八期缺席(前七期连续返回空壳或与数据基建无关的内容),本期四条全部来自英文源。间接的中文侧观察点是 Flink CDC 3.7.0:贡献者名单里有大量中文名开发者,这一版也包含阿里云 MaxCompute sink 的分区修复与 StarRocks sink 的类型映射修正。