datainfra前沿动态 · Vol.65

dbt Projects on Snowflake 把部署单元与执行单元拆开;Dataflow 批作业失败时保住已完成工作;Tiger Data 把 Postgres 写放大测到 10.74 倍;Neon 让 agent 匿名建库、人类事后认领

本期聚焦四条来自 9 月 10 至 11 日的进展:dbt 项目对象支持 Slim CI、defer 与并发执行,Dataflow 批作业失败转为暂停,Postgres 单行写入的物理代价被逐层拆开计量,以及数据库开通这一步被交到 agent 手里。

DataInfra dbt Snowflake Google Cloud Dataflow BigQuery PostgreSQL Neon 写放大 Agent

9 月 10 到 11 日这四件事落在四个毫不相干的层上,做法却指向同一处:把一个原本打包在一起、只能整体对待的动作拆成可以分别计量、分别调度、分别授权的环节。Snowflake 让同一个 dbt 项目对象按切片并行执行,部署单元、执行单元、调度单元从此各走各的,不必再为拆执行频率而复制项目对象。Dataflow 的批作业在失败时改为暂停,已完成的工作不必跟着失败的工作项一起重跑,失败不再是作业的原子终点。Tiger Data 用一段可复制的探针把一行 40 字节的传感器读数拆成堆元组、索引项、WAL 记录三层分别计量,测出 10.74 倍的放大比,并给出拆掉索引后回落到 2.44 倍的对照。Neon 把「创建数据库」与「拥有数据库」拆成两段:agent 匿名开通,人类事后认领,凭证在认领瞬间轮换。四处拆开的代价也各自留下新的边界要管——writeback 冲突、暂停期间的临时目录、放大比的口径、未认领项目的 72 小时寿命。

dbt 项目对象支持 Slim CI 与并发执行:部署、执行、调度三种单元分离

事件概述

Snowflake 于 9 月 10 日宣布,dbt Projects on Snowflake 的 Slim CI、defer to production、失败执行恢复以及并发执行四项能力全部转为正式可用。这批能力的共同点是复用近期生产执行留下的 dbt artifacts(manifest.json、run_results.json),而不是为每次 CI 或开发重建一遍全量模型,也不需要团队自己搭建 artifact 存储。

在此之前,同一个 dbt 项目对象在同一时刻只能承载一次执行。想让核心模型每小时跑、营销模型每十五分钟跑,通常的做法是复制出第二个项目对象,让两个对象各自按自己的节奏执行。复制出来的对象接着要各自维护部署、权限与版本,模型分组越多,对象数量膨胀得越快。

技术解析

  • Slim CI:从最近一次成功的生产执行导入 artifacts,配合 --state 与 --select state:modified+,只校验发生变更的资源及其下游依赖,缩短 CI 执行时间与仓库占用。
  • Defer to production:在 Snowflake Workspaces 或 Snowflake CLI 中,把未构建的上游引用解析到已有的生产关系,而不是在隔离的开发或 CI target 里重建一遍未改动的模型。
  • 并发执行:同一个已部署的项目对象可用 --select path:models/core、--select path:models/marketing 之类的切片并行执行,各自配不同的调度,不必复制对象。前提是处理 writeback 冲突——用 DEFAULT_WRITEBACK 或每次执行的 WRITEBACK=FALSE 关掉回写,或者给每次并发执行指定不同的 --target-path 与 --log-path。
  • 失败恢复:用 result:error+ 这类选择器复用最近一次失败执行的 artifacts,只重跑出错资源及其下游,不重复已经成功的部分。
  • 编译时机可关闭:部署时用 AUTO_COMPILE = FALSE 或 CLI 的 --no-auto-compile 跳过自动编译,配合 Slim CI,并把权限收拢到一个只负责部署的角色上。
  • 前置条件:这套工作流要求 dbt 项目对象使用「单一可变 live 版本」。在 2026_06 行为变更包全面启用之前,需要在账户里显式启用该包;启用后新建与重建的对象走 live 版本,已有的版本化对象可用 SYSTEM$MIGRATE_DBT_PROJECT 迁移。live 版本路径形如 snow://dbt/.../versions/live,一次部署整体替换其内容,执行不会读到部署到一半的项目。

行业影响

把部署单元、执行单元、调度单元拆成三件事之后,「一个项目对象等于一次执行」这个隐含约束就消失了。原本靠复制对象来解决的执行频率差异,现在退回成一条 --select 参数,模型分组的成本从「多一套对象要维护」降到「多一条调度配置」。

代价形态也随之改变:writeback 到共享 live 路径的冲突需要显式关掉或改道,live 版本又是可变的,target 与日志会被下一次部署整体覆盖。换句话说,省掉的是对象复制,新增的是一层需要想清楚的读写约定。

相关链接


Google Data Cloud 一周四条:批作业失败转暂停,insertAll 正式并入 Storage Write API

事件概述

Google Cloud 的《What’s new with Google Data Cloud》周报(9 月 11 日发布,覆盖 9 月 7 日至 10 日)一次给出四条更新:Dataflow 批作业的 pause-on-failure 转为正式可用;沿用多年的 insertAll 流式接口更名为 BigQuery Storage Write API (REST);Pub/Sub 的 AI Inference SMT 转为正式可用;Managed Service for Apache Kafka 的 PostgreSQL 源连接器转为正式可用。四条分属批执行、摄入接口、流处理与 CDC 接入,互不相关。

其中最有工程分量的是 pause-on-failure。Dataflow 批作业以往在重试耗尽后整体失败,已完成的工作项一并作废,重跑成本随数据规模线性上升。新机制把这个终点改成一次可恢复的暂停。

技术解析

  • 触发条件与限制:作业必须是批处理作业,必须使用 Dataflow shuffle,且运行时显式指定 pause_on_failure 服务选项。某个 work item 失败四次后自动暂停;缺货(stockout)与配额错误不会触发暂停,仍按原样失败。暂停期间不能改流水线代码,也不能改 worker 机型。
  • 暂停时长:默认最多保持 7 天,可用 pause_duration 配置在 1 小时到 7 天之间,只支持 h 与 d。超过上限后作业会在下一小时内被取消,取消后无法恢复。
  • 恢复语义:恢复时已完成的工作项不重跑;暂停时正在进行的工作项从头重跑;所有 work item 的失败计数归零,要再失败四次才会再次自动暂停。
  • 计费:Pausing 是中间态,服务在删除 worker VM 之前仍按 VM 计费;进入 Paused 后只对归档的 shuffle 数据计费。
  • 异常行为:手动暂停一个接近完成的作业,它可能直接跑完而不是暂停;极少数情况下作业可能暂停失败——手动暂停的会回到运行状态,因错误暂停的则进入失败状态。
  • insertAll 更名:这个无状态的 JSON-over-HTTPS 端点现在叫 BigQuery Storage Write API (REST),去掉了「legacy」标签,现有用户零代码改动、完全向后兼容,适合 serverless web 应用、IoT 遥测与 AI 日志场景。高吞吐连续管道仍推荐 gRPC 版本。
  • 另两条:Pub/Sub AI Inference SMT 可在事件流上直接调用 Gemini Enterprise Agent Platform 托管的模型,把预测结果追加到事件里再流向 BigQuery 或 Bigtable;Managed Kafka 的 PostgreSQL 源连接器支持从 Cloud SQL for Postgres、AlloyDB 与自建 PostgreSQL 低延迟捕获变更。

行业影响

pause-on-failure 把「作业失败」从原子事件改成一个可停留的中间状态,批作业的容错粒度从作业级下沉到工作项级。对依赖外部服务、容易遇到限流或临时故障的管道,这意味着外部依赖抖动的代价从「整批重跑」降到「修完外部问题续跑」。

值得注意的是缺货与配额错误被明确排除在触发条件之外,暂停期间也不允许改代码和机型——能力边界被写进文档,而不是留给使用者自行试探。这一期里 Dataflow 连着两轮更新(上一期的并行替换与 drain 超时)都落在作业生命周期的可控性上,方向相当一致。

相关链接


一行 40 字节的读数要写 345 字节:Postgres 写放大被逐层拆开计量

事件概述

Tiger Data(TimescaleDB 母公司)在 9 月 11 日的文章里,把「插入一行」这个动作在 PostgreSQL 16 默认配置下的物理代价逐层拆开:在一张带三个索引的表上,一行约 40 字节的传感器读数会触发四条独立的 WAL 记录,提交前日志膨胀约 345 字节。文章给出了可直接复制的探针脚本,让团队在自己最大的表上测出真实放大比,并按风险从低到高列出四种降低手段。

技术解析

  • 元组层:每个堆元组带 23 字节的事务可见性头(t_xmin、t_xmax 等),补齐到 24 字节以满足 8 字节对齐,页面再加 4 字节行指针。实测 pg_column_size 报 64 字节,减去 24 字节头部正好是 40 字节载荷;算上行指针是 68 字节,放大 1.7 倍。追加写入的负载为永不更新的数据付了完整 MVCC 代价。
  • 索引层:Postgres 写入时没有部分索引维护,每个索引都被每次插入同步更新。一个两列 (device_id, ts) B-tree 项约 32 字节(8 字节索引元组头 + 16 字节键 + 4 字节行指针 + 对齐)。单次插入意味着三次 B-tree 下降与三次叶页修改。单调递增的时间戳键会让插入集中落在最右叶页,触发分裂并可能级联到根;高基数索引则把插入打散,命中 shared_buffers 的概率下降。
  • WAL 层:一次堆插入加三次索引插入,正好四条 WAL 记录。叠加 full_page_writes——每个检查点之后数据页的首次修改会把整页内容写进日志——日志量不是稳态的,而是在检查点后冲高再回落。
  • 实测三组数字:向一张 50 万行、三索引的表插入 10 万行,得到 402,099 条 WAL 记录、1,448 个整页镜像、41 MB 日志,对应 3,906 kB 逻辑量,放大比 10.74。去掉开头的 CHECKPOINT 再跑一次,记录数几乎不变(402,286),整页镜像降到 50,日志降到 33 MB,放大比 8.73——两次之间的 8 MB 差额全部由整页镜像解释。再删掉三个索引,记录数降到 100,045,日志降到 9,516 kB,放大比 2.44:这张表上约 70% 的 WAL 是索引维护,不是数据。
  • 换算到吞吐:三索引表的稳态约为每 40 字节行写 345 字节日志。5 万次插入每秒意味着 17 MB/s 日志对应 2 MB/s 读数,这还没算 autovacuum 与任何查询。每多一个索引约多一条记录和 80 字节,五索引表在同样负载下接近 25 MB/s。
  • 四种降低手段(按风险排序):用 COPY 批量写入,多变元组合并进单条 multi-insert WAL 记录,无需改 schema 也不牺牲持久性;对照 pg_stat_user_indexes 的 idx_scan 删掉几乎不被扫描的索引;开启 wal_compression,它压缩的正是整页镜像,代价是写入路径上的 CPU;调大 max_wal_size 与 checkpoint_timeout 以减少检查点,代价是崩溃恢复时间变长、pg_wal 目录变大。
  • 探针的前提:CHECKPOINT 需要 superuser 或 pg_checkpoint 角色,pg_stat_wal 需要 PostgreSQL 14 及以上,两个计数器都是集群级的,必须在静默窗口跑,否则会把别人的写入算进来。

行业影响

写放大一直是「加索引修慢查询、两周后 p95 写入延迟反弹」这类现象背后的机制,缺的是可复现的口径。这篇文章的价值在于把放大比变成一个能用自己的表、自己的硬件跑出来的数字,并给出删索引前后的对照(8.73 对 2.44)——索引的写入税从此可以明码标价。

文章也明确了什么是配置能改、什么是架构才能改:四种手段都在降低写入量,但 24 字节头部与行自身的 WAL 字节是存储引擎的固有属性,压不掉。放大比在四招用尽后仍然偏高时,问题已经不在配置层。这一点对正评估自建与托管 ClickHouse、或考虑列式摄入的团队尤其有用。

相关链接


Neon Claimable Neon:agent 匿名开通数据库,人类事后认领

事件概述

Neon(Databricks 旗下 Lakebase Postgres 的提供方)在 9 月 10 日推出 Claimable Neon,实现 WorkOS 发起的开放协议 auth.md 中的匿名注册方式。agent 在人类不在场、也没有账户的情况下为自己开通一个临时 Neon 项目,拿到限定范围的凭证继续构建;人类后来登录认领,项目转入正式组织。

技术解析

  • 流程四步:agent 先读 llms.txt,再读 neon.com/auth.md 了解机制;neon claim create 匿名注册、创建一个临时项目并返回项目级凭证;agent 用标准 Postgres 客户端连接、跑 SQL、建分支,按需启用 Data API 或 Managed Better Auth;最后生成一个短时认领链接,人类登录后选择组织并接受转移。
  • 配额与寿命:未认领的项目 72 小时后过期,上限 100 MB 存储、1 GB 流量。认领一开始,Neon 立即吊销预认领访问令牌并轮换数据库凭证;agent 若启用了 Managed Better Auth 与 Data API,二者一并转移。项目级的 Neon API key 留在 Claimable Neon 内部,从不返回给 agent。
  • auth.md 的机制:服务在自己的域名根下发布一个 Markdown 文件(路径形如「服务域名 + /auth.md」),内容指向定义端点与所支持流的结构化 OAuth 元数据;agent 据此注册,拿到服务签名的身份断言,再用断言换取短时、限定范围的访问令牌。令牌过期时可用同一断言再次换取,不必共享人类的 API key。协议不绑定 WorkOS 的基础设施。
  • 三种注册方式:agent verified(agent 提供方为已登录用户背书)、user claimed(agent 等待人类登录确认一个码)、anonymous(agent 先拿受限访问,再在人类想保留结果时提供认领流)。Claimable Neon 用的是第三种。
  • 当前开放范围:Neon 数据库(Lakebase Postgres)、Data API、Managed Better Auth 三项,对象存储、Functions、AI Gateway 待跟进。命令形如 neon claim create --service data-api --service auth --env-pull,认领端是 neon claim accept --no-open。Claimable Neon 最终会取代此前的 neon.new。

行业影响

此前业界的注意力集中在「agent 怎么查数据」——Text-to-SQL、语义层、MCP 接口。Claimable Neon 往前挪了一步,把「谁来创建数据库」也交给 agent,人类从流程中的必经节点变成事后可选的确认者。这对数据基础设施的意义是:开通一个后端不再是人的动作,而成了 agent 工作流里可自动完成的一步。

匿名路径的边界同样被写死:固定寿命、小配额、能力需显式授权、令牌短时可吊销、项目级 key 不外出。这些约束决定了它目前只适合原型阶段,而非生产承载。Neon 也把选择匿名的理由说得很直接——与其维护一份已知 agent 产品的白名单,不如公开指令,观察哪些 agent 能发现文件、会请求什么能力、人类最终保留了哪些项目。

相关链接


编者评

本期四条分属编排、批执行、存储引擎、身份开通,看不出共同的产品形态,却能抽出同一个动作:拆开原本被打包在一起、只能整体对待的东西。dbt 把「一次部署一次执行」拆成部署、执行、调度三种独立单元;Dataflow 把「作业失败」从原子终点拆成可停留、可恢复的中间状态;Tiger Data 把「插入一行」拆成堆元组、索引项、WAL 记录三层分别计量;Neon 把「创建并拥有数据库」拆成 agent 匿名开通与人类事后认领两段。

拆开之后的共同收益是:原先只能整体决策的地方,现在可以分别调优——执行频率按切片配、失败只重跑未完成的工作项、放大比可以按索引逐条砍、开通不必等人类。共同代价同样清晰:每拆一次就多出一条必须有人管理的边界。writeback 会撞共享路径,live 版本可变且会被部署整体覆盖;暂停期间不能改代码和机型,临时目录不能删,缺货与配额错误还被排除在触发条件外;放大比依赖集群级计数器,得挑静默窗口测;未认领项目只有 72 小时寿命和 100 MB 配额。

值得留意的是,这些边界都被厂商写进了文档,而不是留给使用者在事故里发现。能力边界的显式化本身,正在成为这轮基础设施演进里与能力同等重要的部分——它决定了「拆开」到底是降低了复杂度,还是只把复杂度挪到了一个更容易看见的地方。

顺带记一笔版本侧的动态:Apache Paimon 已在 9 月 11 日前后放出 2.1.0 的 RC1 与 RC2,PyPaimon 跟进;RisingWave 3.1.0 的首个候选版本也在 9 月 10 日放出。两者都还在候选阶段,正式说明未出,暂不展开。