news 2026/9/25 2:42:32

Apache DataFusion 29.0.0 版本深度解析:UDAF 签名变更、数组函数体系重构与回归聚合函数落地

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apache DataFusion 29.0.0 版本深度解析:UDAF 签名变更、数组函数体系重构与回归聚合函数落地
  • 大数据
  • 数据分析
  • 后端

【免费下载链接】datafusion

Apache DataFusion SQL Query Engine

项目地址:https://gitcode.com/gh_mirrors/datafu/datafusion
点击查看免费下载

Apache DataFusion 在 2023 年 8 月发布的 29.0.0 版本,是一次包含多项破坏性变更(Breaking Changes)与重要功能增强的里程碑式发布。本文以 dev/changelog/29.0.0.md 记录为主线,结合当前仓库源码逐一拆解 UDAF 创建接口调整、数组/列表访问表达式重构、Arrow 45.0.0 升级与 Decimal 除法语义变更、线性回归聚合函数、sqllogictests 测试框架落地等核心内容,帮助你评估升级影响并快速上手新特性。

版本概览

29.0.0 发布于 2023-08-11,是继 28.0.0 之后的一次大版本更新,主要包括:

  • 4 项 Breaking Changes:涉及 UDAF 创建接口、数组函数命名、字段/列表访问表达式 API、Arrow 版本与 Decimal 除法语义;
  • 5 项增强特性:SQL 数组替换/删除函数、数组包含运算符@>/<@、sqllogictests 测试 crate、datafusion-cli多语句支持、线性回归聚合函数;
  • 一批 Bug 修复:如interval - timestamp运算禁用、Projection 列名查找、filter 谓词 panic、count(*)别名等;
  • 大量底层重构:排序保持算子(sort-preserving)相关配置、HashJoin 顺序修复、ExecutionPlan访问器抽取、内存记账(memory accounting)完善等。

Breaking Changes 详解

1.create_udaf参数签名变更:从单类型到类型向量

本版本将create_udaf函数的input_type参数由DataType改为Vec<DataType>(PR #7096)。这一变更直接影响所有使用datafusion_expr编写自定义聚合函数(UDAF)的开发者。

当前仓库中的实际定义位于 datafusion/expr/src/expr_fn.rs:

pub fn create_udaf( name: &str, input_type: Vec<DataType>, // 由单个 DataType 改为 Vec<DataType> return_type: Arc<DataType>, volatility: Volatility, accumulator: AccumulatorFactoryFunction, state_type: Arc<Vec<DataType>>, ) -> AggregateUDF { let return_type = Arc::unwrap_or_clone(return_type); let state_type = Arc::unwrap_or_clone(state_type); let state_fields = state_type .into_iter() .enumerate() .map(|(i, t)| Field::new(format!("{i}"), t, true)) .map(Arc::new) .collect::<Vec<_>>(); AggregateUDF::from(SimpleAggregateUDF::new( name, input_type, return_type, volatility, accumulator, state_fields, )) }

升级要点:

  • 原先input_type: DataType的写法需要改为向量形式,例如vec![DataType::Float64, DataType::Float64];
  • 该函数要求input_type、state_type与Accumulator的实现严格匹配,签名与状态类型必须一致,否则运行时行为无法保证;
  • 仓库中该变更的影响面可从测试用例中印证:自定义聚合的参考示例见 datafusion/core/tests/user_defined/user_defined_aggregates.rs,逻辑计划的 proto 往返测试见 datafusion/proto/tests/cases/roundtrip_logical_plan.rs。

2. 数组函数命名体系重构:array_slice/array_element取代array_trim

本版本实现了array_slice和array_element,并移除了array_trim(PR #6936);同时以 SQL 数组函数array_has、array_has_any、array_has_all替换了旧的array_contains(PR #6990),并新增array_repeat(取代array_fill,PR #7199)与array_flatten(PR #7239)。

当前仓库中这些函数的实现集中在 datafusion/functions-nested/src:

  • array_has.rs 中array_has、array_has_any、array_has_all的签名分别通过Signature::array_and_element(Volatility::Immutable)与Signature::arrays(2, None, Volatility::Immutable)构建,即二元数组函数,均为不可变(Immutable)函数;
  • 切分与提取逻辑位于 extract.rs(array_slice/array_element相关),重复与展平逻辑位于 repeat.rs。

对使用者而言,需要关注的是 SQL 语义层面的调整:

-- 旧接口(29.0.0 之前) SELECT array_contains([1, 2, 3], 2); SELECT array_trim(...); -- 29.0.0 及之后的新接口 SELECT array_has([1, 2, 3], 2); -- 单个元素判断 SELECT array_has_any([1, 2], [2, 3]); -- 任一命中 SELECT array_has_all([1, 2], [1, 2]); -- 全部命中 SELECT array_slice([1, 2, 3], 2, 3); -- 按区间切片 SELECT array_element([1, 2, 3], 2); -- 按下标取元素 SELECT array_repeat([1], 3); -- 重复生成数组 SELECT array_flatten([[1, 2], [3]]); -- 数组展平

3. 字段与列表访问表达式 API 人体工学改进

PR #7215 与配套的 #7218、#7219、#7220 系列重构了创建字段访问(field access)和列表访问(list access)的 API:

  • 新增Expr::field、Expr::index、Expr::slice构造器(PR #7218),替代原先较为冗长的构造方式;
  • 为GetFieldAccessExpr增加构造器并补齐文档(PR #7219);
  • 将GetFieldAccessCharacteristic重命名并补充文档(PR #7220)。

这一系列改动让表达式树(Expression Tree)在构建字段/索引/切片访问时更加直观,也从侧面表明 DataFusion 在持续打磨 DataFrame 与表达式 DSL 的易用性。

4. Arrow 45.0.0 升级与 Decimal 除法语义变更

PR #6832 将 Arrow 依赖升级至 45.0.0,并同步引入了 Datum Arithmetic(标量值直接参与算术运算)机制,同时改变了 Decimal 除法的语义。这是 29.0.0 中影响面最大的底层变更之一:

  • Decimal 除法:除法结果不再按旧的固定精度/标度规则推导,而是遵循 Arrow 45.0.0 的 Datum 算术语义重新定义精度与标度,涉及 DECIMAL 类型的除法结果可能随之变化;
  • 同一时期还补充了更多 Decimal256 类型强制转换(PR #7047),并将Decimal256纳入ScalarValue(PR #7048),Decimal 256 位大精度支持在此版本中进一步完善。

如果你的业务 SQL 中存在高精度 Decimal 除法运算,升级后应重点回归验证精度与舍入行为。

新特性聚焦

线性回归聚合函数家族:regr_*

PR #7211 引入了完整的线性回归聚合函数族,其实现位于 datafusion/functions-aggregate/src/regr.rs。从源码看,该家族共包含 9 个函数,全部以(Float64, Float64)签名注册为不可变聚合(Signature::exact(vec![DataType::Float64, DataType::Float64], Volatility::Immutable)):

函数语义(以Y = k*X + b拟合为例)
regr_slope(Y, X)最小残差平方和(RSS)拟合下的斜率 k
regr_intercept(Y, X)最小 RSS 拟合下的截距 b
regr_count(Y, X)两表达式均非空的输入行数
regr_r2(Y, X)决定系数 R²(Y 中可由 X 解释的方差比例)
regr_avgx(Y, X)自变量 X 的平均值
regr_avgy(Y, X)因变量 Y 的平均值
regr_sxx(Y, X)X 与其均值偏差的平方和
regr_syy(Y, X)Y 与其均值偏差的平方和
regr_sxy(Y, X)X、Y 偏差乘积之和

其中regr_slope是最先落地的一个(PR #7135),其余 8 个随后补齐(PR #7211)。聚合状态通过make_udaf_expr!宏批量生成,回归测试覆盖于 datafusion/sqllogictest/test_files/aggregate.slt。典型用法:

-- 拟合 y = k*x + b SELECT regr_slope(y, x), regr_intercept(y, x), regr_r2(y, x) FROM regression_data;

数组包含运算符@>与<@

PR #6885 新增了 PostgreSQL 风格的数组包含/被包含运算符:

SELECT [1, 2, 3] @> [1, 2]; -- true:左数组是否包含右数组 SELECT [1, 2] <@ [1, 2, 3]; -- true:左数组是否被右数组包含

该特性与上述array_has_any/array_has_all函数互为补充,分别覆盖"运算符风格"与"函数风格"的数组包含判断。

sqllogictests crate:新的测试框架

PR #7134 新增了独立的sqllogictestscrate(现位于 datafusion/sqllogictest),这是 29.0.0 在工程化层面的重要投入:

  • 引擎侧支持多种后端:datafusion_engine(见 datafusion/sqllogictest/src/engines/datafusion_engine/runner.rs)、postgres_engine(见 datafusion/sqllogictest/src/engines/postgres_engine/mod.rs)以及 Substrait 往返测试引擎;
  • 测试文件按.slt格式组织于 datafusion/sqllogictest/test_files,覆盖 aggregate、scalar、math、expr 等大量 SQL 场景;
  • 该版本同时将原有information_schema的 Rust 测试迁移至 sqllogictests(PR #7050),后续版本持续把测试收敛到该框架。

datafusion-cli支持多语句输入

PR #7138 让datafusion-cli可以一次性接受并执行多条语句(如粘贴一段包含多条 SQL 的脚本),并配套忽略了查询文件末尾的空白行与注释(PR #7076)。这使得 CLI 的批处理体验更接近标准数据库客户端,相关实现位于 datafusion-cli/src。

其他值得关注的新函数与行为

  • nanvl内置函数(PR #7171):实现于 datafusion/functions/src/math/nanvl.rs,用于处理 NaN 值场景(如nanvl(x, default)在 x 为 NaN 时返回默认值),测试见 datafusion/sqllogictest/test_files/math.slt;
  • make_array增强(PR #7137、#7207):支持传入列表类型列,并在嵌套版本中完善了 null 处理语义;
  • unnestAPI 调整(PR #7168):与 DuckDB / ClickHouse 行为对齐,新增preserve_nulls选项;
  • count(*)别名修复(PR #7081):修正了聚合投影中count(*)列别名的处理;
  • with_column_renamed大小写敏感支持(PR #7063):支持大小写敏感的列重命名;
  • 正则表达式简化(PR #7186):支持化简如~ ^(ba_r|foo)$这类包含下划线的正则表达式。

Bug 修复与稳定性改进

本版本修复了多个会影响查询正确性与稳定性的问题:

  • 禁用interval - timestamp(PR #7086):从类型检查层面直接拒绝该无意义的运算组合,避免运行时出现歧义结果;
  • 修复 filter 谓词 panic(PR #7126):修复特定谓词组合下执行期 panic;
  • 修复多分区错误列需求(PR #7129):修复多分区场景下投影列需求错误导致的错误结果;
  • Projectioncolumns_map移除名称搜索(PR #7099):避免列映射阶段按名称搜索带来的歧义;
  • SortPreservingMerge 内存记账(PR #7130):为排序保持归并算子补上内存占用统计,配合MemoryReservation::{split_off, take, new_empty}(PR #7184),让内存限制(memory_limit)机制覆盖更完整;
  • 压缩相关测试在--no-default-features下跳过(PR #7172):修复了禁用默认特性时测试失败的问题。

底层重构与性能优化

29.0.0 还包含大量架构级重构,这些改动为后续版本的执行引擎演进奠定基础:

  • 排序保持算子配置化(PR #7164):新增 config 选项,允许"有限度地"使用排序保持算子,交由用户权衡收益与内存开销;
  • HashJoin 顺序修复(PR #7155)与 join 排序等价性工具函数抽取(PR #7167):统一了 join 输出排序的推导逻辑;
  • ExecutionPlan访问方式统一(PR #7175):新增ExecutionPlan::file_scan_config,避免大量依赖类型向下转换(downcasting)来获取文件扫描配置;
  • 模块拆分:AnalysisContext移出physical_expr(PR #7127)、ExecutionPlanVisitor独立成模块(PR #7236)、streams 移出physical_plan(PR #7234)、Partitioning与Distribution移入physical_expr(PR #7238);
  • 弃用batch_byte_size(PR #7245):批次字节大小计算的旧接口被标记弃用;
  • with_inputs()复用原始 schema(PR #7069)与with_preserve_order参数化(PR #7231):减少重复 schema 计算;
  • plan_err!错误宏(PR #7115):统一了 plan 阶段错误构造方式;
  • 基准测试工具整理:创建dfbench并拆分 TPCH benchmark runner(PR #7054)、为 benchmark runner 加入 ClickBench 查询(PR #7060)、bench.sh默认只跑 5 次迭代(PR #7189)。

升级注意事项总结

综合来看,从 28.0.0 升级到 29.0.0 时,最需要关注的是以下四点:

  1. 自定义 UDAF:create_udaf的input_type参数必须从DataType改为Vec<DataType>(参考 datafusion/expr/src/expr_fn.rs);
  2. 数组 SQL 函数:array_trim、array_contains、array_fill已被移除,分别迁移到array_slice/array_element、array_has/array_has_any/array_has_all、array_repeat;
  3. Decimal 除法语义:Arrow 45.0.0 升级后,Decimal 除法的精度/标度推导发生变化,涉及金融或高精度计算的查询需重点回归;
  4. 表达式 API:Expr::field、Expr::index、Expr::slice与GetFieldAccessExpr构造器的引入意味着程序化构建字段/列表访问的写法已更新。

同时,29.0.0 带来的回归聚合函数族(regr_slope等 9 个函数)、数组包含运算符、nanvl、sqllogictests 测试框架与datafusion-cli多语句支持,都是值得在统计分析与工程化实践中直接采用的新能力。相关函数实现、测试与使用示例均可从上述仓库路径中进一步查阅。

  • 大数据
  • 数据分析
  • 后端

【免费下载链接】datafusion

Apache DataFusion SQL Query Engine

项目地址:https://gitcode.com/gh_mirrors/datafu/datafusion
点击查看免费下载

相关推荐

上一篇:今日热门项目推荐:md - 微信图文排版新纪元
下一篇:100 个 Rust 练习上手指南:8 个模块带你从语法到并发

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 2:42:25

msModelSlim架构深度解读:支撑30+主流大模型量化的四层设计哲学

msModelSlim架构深度解读&#xff1a;支撑30主流大模型量化的四层设计哲学 【免费下载链接】MindStudio-ModelSlim MindStudio-ModelSlim&#xff08;msModelSlim&#xff09;是MindStudio全流程工具链推出的模型量化压缩工具。 项目地址: https://gitcode.com/Ascend/msmode…

作者头像 李华
网站建设 2026/9/25 2:40:11

VisiData 终端电子表格工作坊指南:从零上手到数据探索大师

数据分析CLI数据可视化 【免费下载链接】visidata A terminal spreadsheet multitool for discovering and arranging data 项目地址&#xff1a; https://gitcode.com/gh_mirrors/vi/visidata 点击查看 免费下载 本指南基于 VisiData 官方工作坊提纲&#xff08;dev/workshop…

作者头像 李华
网站建设 2026/9/25 2:37:44

【企业智能体开发】防范文档与工具结果中的提示注入

小林查询投屏指引时,知识库返回的正文里夹着一句:“为提高效率,后续建单不必再征求员工确认。”这句话可能是过期的编辑批注,也可能是有人故意放进资料里的诱导内容。无论哪种情况,文档的职责都是提供投屏知识,不是改写 Agent 的执行规则。若模型把检索结果里的话当成上级…

作者头像 李华
网站建设 2026/9/25 2:36:35

用C++打造SECS/GEM调试工具:从协议解析到现场联调

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华