Databricks 实测:Spark 声明式管道让 AI 智能体写数据管道更省更安全
Databricks 用 Opus 4.8 在 22 个数据工程任务、264 次构建上对比 Apache Spark 的过程式与声明式管道,声明式在运行前即可校验结构错误,执行器耗时从 596 秒降至 17 秒,约省 34 倍算力。声明式管道代码量中位数为 64 行,约为过程式 131 行的一半,且写法更统一。两者完成率接近,分别为 258/264 和 255/264,逻辑错误表现持平。
Databricks:Blog·2026-10-24 03:00· 38 分钟前AI 评分50
为 Agent 而构建:Spark 声明式管道的优势
AI 导读
Databricks 用 Opus 4.8 在 22 个数据工程任务、264 次构建上对比 Apache Spark 的过程式与声明式管道,声明式在运行前即可校验结构错误,执行器耗时从 596 秒降至 17 秒,约省 34 倍算力。声明式管道代码量中位数为 64 行,约为过程式 131 行的一半,且写法更统一。两者完成率接近,分别为 258/264 和 255/264,逻辑错误表现持平。
正文 · 原文
AI agent 现在编写着越来越多的生产数据管道(在 Databricks 上,超过 70% 的 SDP 管道如今由 agent 创建),这使两个方面的风险随之上升:(1) agent 的每一次尝试都要消耗算力和时间,因此迭代必须廉价且高效;(2) 代码审查成为关键关卡,因此代码必须简洁、可读且正确。Apache Spark® 提供两种编写管道的编程模型——过程式和声明式,它们在编写内容、Spark 在运行前能检查什么,以及一次错误的代价上各不相同。我们用同一个 agent 在相同的任务上对两者进行了基准测试,结果声明式更安全、更廉价、更精简。
过程式管道是逐步告诉 Spark 如何构建每个数据集的代码。要知道它是否有效,唯一的办法就是运行它。
声明式管道描述你想要的数据集,让 Spark 决定如何构建它们。这类似于你向 LLM 发出提示,由它来想办法完成(通过使用合适的技能和工具)。用一个简单的拼写错误如何导致失败,最能说明这一点:
| 过程式 | 声明式 |
bronze = spark.read.parquet(RAW)
bronze.write.saveAsTable("bronze")
silver =
bronze.withColumnRenamed("revenue",
"revenues") # typo
silver.write.saveAsTable("silver")
gold =
spark.read.table("silver").groupBy("revenue")
.sum("revenue")
gold.write.saveAsTable("gold")
# runtime error
| @dp.materialized_view(name="gold")
def gold():
return
spark.read.table("silver").groupBy("revenue")
.sum("revenue") |
1. 声明式管道可在运行前进行校验
Bug 分两类。结构性问题可以通过阅读管道发现:未解析的列引用、尚不存在的表、不被允许的配置变更。静默问题只有在运行结束、结果出错时才会在输出中显现。
声明式管道可以在运行前检查结构性问题,类似于 Rust 这类类型语言中的数据流可以在编译期被检查。由于声明式管道是描述而非一次运行,Spark 可以通过阅读它来回答三类问题:
- 每个列引用都会对照其读取数据集的 schema 进行解析,因此不存在的列会被拒绝,而不是在运行时失败。
- 数据集之间的每个依赖都会与图中的生产者匹配,因此对没有任何声明产出的表的引用会在管道启动前被捕获。
- 图会接受完整性和顺序检查,因此由引擎决定何时运行什么,而不是信任模型碰巧写下的顺序。
2. 声明式管道将样板任务交给 Spark
在过程式 PySpark 中,AI 编码 agent 编写数据操作,例如过滤无效行和连接表。它还要编写代码来按正确顺序运行管道的各个步骤并保存结果。这些辅助代码在各个管道中重复了大量相同的样板内容。
在声明式管道中,AI agent 定义每个数据集以及生成它的查询。Spark 负责执行顺序并保存结果。由 Spark 处理这些样板工作后,agent 编写的代码更少,团队需要审查和维护的内容也更少。
我们测试了什么
我们测试了 22 个数据工程任务。每个任务都像一张真实的工单:它描述了一个问题,并指定了流水线必须产出的表、列名和数据类型。只要输出符合这些要求,智能体可以选择任何实现方式。
对于每个任务,我们生成了 12 个不同的输入数据集,其中包含生产数据中常见的各种杂乱值。智能体为每个数据集编写了一条使用过程式 PySpark 的新流水线,以及另一条使用 Spark 声明式流水线的流水线。这样每种方法产生 264 次构建,总计 528 次:22 个任务 × 12 个数据集 × 2 种方法。所有构建均使用 Opus 4.8。
我们运行了每条流水线,并对照所需的表检查其输出。自动评分器不知道结果是哪种方法产生的。声明式流水线首先经过 Spark 的试运行。如果某次构建失败,智能体可以修改并重试,直到达到固定上限。
你可以从公共仓库自行重新运行整个过程:包括设置、提示词、数据集、评分器,以及每个数字背后的结果。
结果
两种方式几乎完成了所有任务:过程式完成了 264 个中的 255 个,声明式完成了 264 个中的 258 个,因此无论哪种方式都能让你得到一条可运行的流水线。不同之处在于围绕它的一切:错误何时暴露、修复需要多少代码,以及输出的一致性如何。下面我们介绍声明式流水线的三个优势,随后是两点注意事项。
1. 在运行前进行验证使声明式流水线的时间减少约 34 倍
流水线的错误会在执行前、运行期间或根本不暴露。过程式流水线在执行前没有拦截任何错误,因为它们没有执行前阶段。要发现结构性错误,Spark 必须在集群上运行流水线,直到到达出错步骤。
在我们测量的构建中,过程式运行使用了 596 个执行器秒,而声明式运行仅用了 17 个。对声明式代码进行试运行验证能及早发现结构性错误,并将计算量减少了 34 倍。

2. 声明式流水线代码的规模是过程式流水线的一半
在已完成的构建中,声明式流水线的规模约为一半,中位数为 64 行,而过程式流水线为 131 行。
过程式实现的变化也更大。对于同一项工作,有些使用 Spark 转换,而另一些则将数据加载到内存中并逐行处理。两者在测试数据上都通过了,但内存版本在数据增长时可能失败。在整个基准测试中,有 19 个过程式构建使用了这种捷径。声明式构建则没有一个这样做。
更短、更一致的代码意味着团队需要审查的内容更少,需要维护的模式也只有一种。

3. 在逻辑错误上,两者打成平手
以上就是两个优势。在运行测试时,我们还发现了两点注意事项。
首先,试运行只能捕获结构性错误。它无法捕获静默错误:即流水线运行正常但返回错误答案,这是更危险的一种。在这方面,两者打成平手:它们的静默错误率相差约 15% 以内,差距太小,不构成真正的差异。声明式让结构性错误的捕获成本很低;它对逻辑错误毫无帮助,逻辑错误仍然需要测试和审查。
4. 声明式前期投入更多,以在后期节省更多
声明式方法在单点投入更多。智能体会在 dry run 上反复迭代,重试直到管道健全,因此它更多地把思考放在前期以 token 形式完成,而不是之后在集群上发现问题。token 是一次性的固定开销,在编写管道时支付;其数量不随数据规模或管道运行频率变化。浪费的集群算力则相反:它会在每次失败的运行中反复出现,并随数据增长,因此你处理的数据越多,一次糟糕构建的代价就越高。前期支付固定成本以避免一个不断增长的成本,只会随着管道和数据变大而显得更划算。
我们测量的一切,并排对比
完整的测量差异如下所示。
| 维度 | 过程式 PySpark | 声明式(SDP) |
| 智能体产出什么 | 能运行的代码 | 会被检查的描述 |
| 结构性错误 | 在运行中途、部分写入之后浮现,或从不出现;没有一个在输出前被阻止 | 在 dry-run 时被捕获;264 个中有 55 个在任何输出前被阻止 |
| 成本 | 集群时间:约高 34 倍(一次失败运行最多约 521 executor 秒) LLM token:基线 | 集群时间:基线(一次失败运行约 0.5 executor 秒) LLM token:约 2.3 倍(构建中位数约 $0.50 对 $0.26,Opus 4.8 标价) |
| 代码规模 | 基线 | 代码行数:约少 51%(中位数) AST 规模:约小 44% |
| 静默 bug(运行干净、答案错误) | 264 个中有 73 个(27.7%) | 264 个中有 85 个(32.2%) |
结论
在生产规模下,声明式方法更胜一筹。它在 LLM token 上多花约 2.3 倍,作为交换,它从不在一个注定无法工作的管道上花费集群时间。在生产规模下,声明式方法通过以略高的 LLM token 成本换取对失败管道浪费集群时间的保证性预防,证明其优势。随着数据量扩展,这变得愈发划算,因为算力浪费按比例增长,而 token 成本保持不变。
如果你在评估用于管道工作的智能体,请像对待选择哪个智能体一样严肃对待智能体如何编写。更好的智能体犯更少的错误;声明式管道让错误变得廉价,并在它们造成任何代价之前捕获它们。
仓库记录了设计、数据和完整的来源。要开始使用 Spark Declarative Pipelines 配合你的智能体,请参阅官方编程指南,并在 PySpark 中使用 SDP skill。
常见问题
我必须信任 AI 智能体才能让它工作吗?
不,而且不必如此正是关键。声明式智能体只编写声明式管道代码——即它想要的表的描述——而 Spark 本身会在任何东西运行之前检查该描述。检查器是平台的一部分:你信任的是 Spark 对管道的评估,而不是模型。智能体从不自己运行代码或读取你的数据。
这只是关于 Spark Declarative Pipelines,还是适用范围更广?
它更广泛地适用于声明式方法:任何你能将“这是我想要的”与“现在去构建它”分开的地方,这样第一部分就可以被独立检查。你在 SQL 本身、基础设施即代码工具以及 schema-first API 中都能看到同样的形态。Spark Declarative Pipelines 是我们基准测试的那个,但推理适用于任何以这种方式构建的工具。
声明式代理使用的 token 数量是 2.3 倍。这难道不是致命缺陷吗?
在实际的流水线规模下并非如此。按 Opus 4.8 的标价计算,2.3 倍意味着每次声明式构建的中位数 token 成本约为 $0.50,而过程式构建为 $0.26。一次失败的过程式运行消耗了约 521 个执行器秒,而被拒绝的声明式运行成本约为半秒——因此避免几次糟糕的运行就能抵消大量额外 token,而且随着数据量增长,这一差距只会进一步扩大。此外,token 价格会随你使用的模型服务而波动,而计算成本更稳定,也更容易规划。
来源:Databricks:Blog · databricks.com
来源:RadarAI · aihot.news