Apache DataFusion 49.0.0 版本解析:Equivalence 系统重构、Parquet 模块化加密与性能优化全景
大数据数据分析后端【免费下载链接】datafusionApache DataFusion SQL Query Engine项目地址https://gitcode.com/gh_mirrors/datafu/datafusion点击查看免费下载导读本文基于 Apache DataFusion 官方发布的 49.0.0 版 changelogdev/changelog/49.0.0.md对该版本从源码层面进行完整解读。49.0.0 是一个包含 253 个提交、由 71 位贡献者共同完成的里程碑版本其核心看点包括Equivalence等价性系统的大规模重构、Parquet 模块化加密正式落地、MSRV 提升至 1.85.1以及多项针对 Parquet 剪枝、哈希连接和字符串视图的深度性能优化。读完本文你将掌握该版本的破坏性变更清单、新增配置项的完整用法以及底层实现原理与升级迁移路径。版本概览253 个提交与 71 位贡献者Apache DataFusion 49.0.0 是 DataFusion 在查询引擎演进道路上的一个重要版本。根据 dev/changelog/49.0.0.md 的记录本次发布共合并了253 个提交来自71 位贡献者。其中提交数领先的贡献者包括 Andrew Lamb33 个、Adrian Garcia Badaracco19 个、kosiew14 个、Piotr Findeisen13 个、Qi Zhu13 个等依赖机器人 dependabot[bot] 也贡献了 26 个依赖升级提交。该版本的变更集中在以下几个方向破坏性变更Breaking changes9 项涉及 API 形态、错误处理、MSRV 等性能优化Performance related9 项覆盖 Parquet 剪枝、哈希连接、字符串视图排序等热点路径新特性Implemented enhancements16 项包括 Parquet 模块化加密、RightMark 连接、新的标量函数等Bug 修复与文档更新数十项覆盖规划器、执行器、SQL 解析与 CLI 等模块。与以往版本类似官方同时提供了 49.0.0 升级指南用于帮助用户从旧版本平滑迁移。本文后续内容将逐一展开这些变更的细节与源码依据。破坏性变更升级前必须了解的 9 项变化49.0.0 的破坏性变更直接影响 API 使用方式升级前需要重点评估。以下逐项说明其含义与影响范围。Equivalence System Overhaul等价性系统全面重构本次版本中最重要的一项变更标记为[MAJOR]是Equivalence System Overhaul#16217。该重构由 Mehmet Ozan Kabak 主导旨在重新设计 DataFusion 物理计划中的表达式等价性追踪机制。在 DataFusion 的物理优化器中等价性信息用于判断哪些表达式恒等以及哪些排序ordering等价从而支撑排序消除、连接重排、投影合并等优化。重构后的核心数据结构可以在 datafusion/physical-expr/src/equivalence/properties/mod.rs 中看到EquivalenceProperties现在由五个组成部分协作pub struct EquivalenceProperties { eq_group: EquivalenceGroup, // 值等价的表达式分组 oeq_class: OrderingEquivalenceClass, // 定义相同排序的等价排序表达式 oeq_cache: OrderingEquivalenceCache, // 排序等价缓存normal form constraints: Constraints, // 参与等价计算的表约束 schema: SchemaRef, // 关联的模式 }其中EquivalenceGroup见 datafusion/physical-expr/src/equivalence/class.rs通过IndexMap实现表达式到等价类的高效查找OrderingEquivalenceClass见 datafusion/physical-expr/src/equivalence/ordering.rs则维护一组互相等价的LexOrdering并保证集合中不存在一个排序是另一个排序后缀的冗余不变式以最小化存储。该重构属于破坏性变更意味着依赖旧等价性 API 的第三方物理优化器代码需要跟随调整。错误处理重构DataFusionError 变体改为 Box 封装#16672 将DataFusionError的多个变体改为 boxed 错误以减小错误枚举的占用空间从而降低ResultT, DataFusionError的体积、栈占用以及 async 状态机的大小。根据升级指南docs/source/library-user-guide/upgrading/49.0.0.md受影响的变体包括ArrowErrorSQLSchemaError迁移示例此前构造SchemaError变体直接内联错误对象DataFusionError::SchemaError( SchemaError::DuplicateUnqualifiedField { name: foo.to_string() }, Box::new(None) )现在需要将内部错误显式装箱DataFusionError::SchemaError( Box::new(SchemaError::DuplicateUnqualifiedField { name: foo.to_string() }), Box::new(None) )凡是在代码中构造或模式匹配这三个变体的位置都必须相应更新。SortExec 与 AggregateUDF 清理删除未使用的 API#16457 移除了SortExec中不再使用的多个方法#16683 删除了未使用的AggregateUDF结构体。这些都属于内部 API 清理对常规使用者影响有限但若有第三方代码引用了被删除的符号需要同步调整。剪枝逻辑独立成 cratedatafusion-pruning#16549 目录下可以看到该 crate 的完整结构file_pruner.rs基于文件级统计信息file-level statistics执行剪枝的FilePrunerpruning_predicate.rs构建剪枝谓词的PruningPredicatein_list.rs/primitive_in_list.rs/string_in_list.rs针对IN列表谓词的专项优化。以FilePrunerdatafusion/pruning/src/file_pruner.rs为例它接收一个物理谓词表达式通过DynamicFilterTracking追踪其中的动态过滤器只有当被观察的动态过滤器真正变化时才重建剪枝谓词避免不必要的重复构建。这一重构影响依赖旧剪枝路径的 crate 用户属于破坏性变更。其他破坏性变更ExecutionOptions::time_zone类型修复#16569部分函数如now()会依据该时区返回时间戳。排序表达式从OptionVec...改为Vec...#16615简化 API 形态。RowCursorStream复用 Rows 分配#16647属于内部优化同时简化了 API。SchemaError缩小#16653减少错误枚举体积。MSRV 提升至 1.85.1#16728 中指定的工作区默认工具链已经是更新版本1.98.1但作为库使用者需要保证自己的 Rust 工具链不低于 1.85.1。性能优化从 Parquet 剪枝到哈希连接的九项改进49.0.0 在性能方面投入显著多项优化直接作用于查询执行的热点路径。Parquet 文件级统计的后期剪枝Late Pruning#16014 为 Parquet 扫描增加了基于文件级统计信息的后期剪枝能力。传统上谓词下推会在扫描之前利用列统计信息过滤文件/行组而后期剪枝则允许在谓词尤其是动态过滤器已经生成之后再对尚未开始读取的文件执行一轮基于文件级统计的过滤从而避免读取那些确定不满足条件的文件。这一能力与FilePrunerdatafusion/pruning/src/file_pruner.rs配合其剪枝谓词通过PrunableStatistics判断文件是否可能包含匹配的行。配合 #16424 的优化当不存在动态过滤器时跳过基于分区值和文件级统计的重复剪枝避免无谓的开销。每个文件单独的过滤求值Per-file filter evaluation#15057 将过滤表达式的求值从批级别细化到逐文件维度并让过滤表达式适配文件自身的 schema#16461。这为异构 schema 的文件集提供了更精确的过滤路径也是 #16732 重构过滤下推 API使 Join 也能传递过滤器的基础。默认开启统计收集collect_statistics 默认值改为 true#16447/// Should DataFusion collect statistics when first creating a table. /// Has no effect after the table is created. Defaults to true. pub collect_statistics: bool, default true注意该设置在表创建之后不再生效Has no effect after the table is created。对于依赖旧默认行为不收集统计的用户需要显式设置SET datafusion.execution.collect_statistics false;或通过SessionConfig::with_collect_statistics(false)恢复旧行为。仓库中的 datafusion/sqllogictest/test_files/parquet_statistics.slt 等 SLT 测试对统计收集行为有大量回归验证。StringViewArray 比较路径优化#16509 针对 Arrow 的StringViewArray优化了CursorValues的比较性能官方 changelog 中标注其使sort-tpch Q11 查询提速约 1.4 倍。其原理是复用 Arrow 侧的内联键inline key快速比较技巧相关修复见 #16698 与 #16630大幅减少排序过程中对字符串内容的解引用访问。哈希连接相关优化#16716 优化了 build 侧为空时的哈希连接空 build 侧不需要构建哈希表直接输出空结果#16434 为HashJoinExec增加了u32索引支持降低连接过程中的索引内存开销#16083 与 #16488 为 NestedLoop 和 Hash 连接增加了RightMark连接支持其中 RightMark 的最终化曾在 #16597 中被临时回退随后在 #16488 重新合入。其他性能改进#16389为try_process_unnest增加快速路径#16362在PushDownFilter优化规则中简化谓词#16706优化结构化类型structural types的ScalarValue::to_array_of_size#16734MemorySource自动将过大的单个 RecordBatch 拆分为更小的批次。新特性Parquet 模块化加密与一批实用函数Parquet 模块化加密Modular Encryption#16351 为 DataFusion 引入了Parquet 模块化加密能力。Parquet 模块化加密是 Parquet 格式规范中的安全特性支持对文件不同部分footer、column metadata、data pages 等使用不同的加密密钥与算法实现列级乃至细粒度的访问控制。从源码结构看加密相关的实现分布于多个模块datafusion/common/src/encryption.rs加密工厂与加解密属性的公共定义datafusion/datasource-parquet/src/opener/encryption.rsParquet 文件读取端的加密处理datafusion/common/src/file_options/parquet_writer.rs写入端的加密选项。配置层面datafusion/common/src/config.rs 定义了ParquetEncryptionOptions包含三个可选字段pub struct ParquetEncryptionOptions { /// 可选的解密属性 pub file_decryption: OptionConfigFileDecryptionProperties, /// 可选的加密属性 pub file_encryption: OptionConfigFileEncryptionProperties, /// 用于创建加解密属性的加密工厂标识 pub factory_id: OptionString, /// 加密工厂专属选项 pub factory_options: EncryptionFactoryOptions, }关键前提使用 Parquet 加密必须启用parquet_encryptionfeature flag该 feature 默认不激活见 datafusion/common/src/config.rs 的说明。加密工厂需要先通过RuntimeEnv::register_parquet_encryption_factory注册到运行时环境中然后通过ParquetEncryptionOptions::configure_factorydatafusion/common/src/config.rs绑定工厂 ID 与配置。升级指南也提示TableParquetOptions结构体新增了crypto字段默认值为Default::default()此前用结构体字面量构造TableParquetOptions的代码需要补充该字段。此外#16649。RightMark / Mark Join 支持#16488 最终完成了RightMark连接Markjoin 的交换版本支持并在MarkJoin算法的注释中补充了实现说明#16436。Mark Join 是 DataFusion 用于支持EXISTS/NOT EXISTS子查询改写的一类连接算子RightMark 的补齐意味着更多相关子查询模式可以被高效执行。文档层面#16316 为 SEMI ANTI 连接补充了 SQL 示例。新的标量函数与内置函数array_min#16574返回数组中的最小值map_entries#16557返回 map 的键值对条目regex_instr#15928正则匹配位置查询函数array_has#16333与array reverse#16423增加了对FixedSizeList的支持to_hex扩展支持UInt64等更多整数类型#16335factorical阶乘函数进入 datafusion-spark 兼容函数库#16125。SQL 类型映射与字符串视图#16290 实现了 SQLCHAR/TEXT/STRING默认映射到 Arrow 的Utf8View类型。Utf8View是 Arrow 社区引入的零拷贝字符串视图格式可避免全量 UTF-8 拷贝降低内存占用与分配开销。这一映射行为受新配置项控制详见下文新配置项章节。其他值得关注的新特性自定义 MetricValues#16195支持在 PhysicalPlan 中定义自定义指标值CPU 密集聚合操作的取消支持#16196允许取消纯 CPU 密集的聚合操作SchemaProvider::table_type#16401为 SchemaProvider 增加表类型查询接口DataFrame API 暴露 intersect distinct / except distinct#16578异步 UDF 支持#14837引入异步用户自定义函数Async UDF并在 #16523 中简化AsyncScalarUdfImpl使其继承自ScalarUdfImpl表达式字面量元数据#16170为 literal 表达式添加元数据支持后续通过FieldMetadata结构统一承载#16317、#16320。新配置项详解四个影响行为的开关49.0.0 引入或调整了若干配置项本节给出完整用法与底层实现。datafusion.sql_parser.map_string_types_to_utf8view默认 true该配置统一了所有SQL 字符串类型CHAR、VARCHAR、TEXT、STRING到 ArrowUtf8View的映射替代了旧的map_varchar_to_utf8view后者已废弃。定义见 datafusion/common/src/config.rs/// If true, string types (VARCHAR, CHAR, Text, and String) are mapped to Utf8View during SQL planning. /// If false, they are mapped to Utf8. pub map_string_types_to_utf8view: bool, default true为true默认时所有 SQL 字符串类型在 SQL 规划阶段映射为Utf8View为false时回退到传统的Utf8映射。通过 SQL 全局关闭SET datafusion.sql_parser.map_string_types_to_utf8view false; -- 现在 VARCHAR、CHAR、TEXT、STRING 都使用 Utf8 而非 Utf8View CREATE TABLE my_table (a VARCHAR, b TEXT, c STRING); DESCRIBE my_table;通过 Rust API 在解析器选项层面控制参见升级指南 docs/source/library-user-guide/upgrading/49.0.0.mdlet opts datafusion::sql::planner::ParserOptions::new() .with_map_string_types_to_utf8view(false);datafusion.execution.spill_compression默认 uncompressed#16268Keydatafusion.execution.spill_compression默认值uncompressed合法取值uncompressed、lz4_frame、zstd注意解析逻辑对大小写不敏感且空字符串等价于uncompressed非法取值会返回DataFusionError::Configuration错误。使用方式let config SessionConfig::default() .with_spill_compression(SpillCompression::Zstd); let ctx SessionContext::new_with_config(config);或者通过 SQL 动态设置SET datafusion.execution.spill_compression zstd;选择zstd通常能获得更高的压缩率而lz4_frame更偏向压缩/解压速度。此外#16535 修正了spilled_bytes指标使其反映真实的磁盘使用量压缩后配套的微基准测试见 #16512。datafusion.execution.collect_statistics默认改为 true如前述该配置在 49.0.0 中默认值由false改为true。含义首次创建表时是否收集统计信息供优化器使用。表创建后该设置不再生效。恢复旧行为的方式SET datafusion.execution.collect_statistics false;ExecutionOptions::time_zone类型修正time_zone的类型修正为OptionString默认None见 datafusion/common/src/config.rs某些函数如now()在此基础时区上返回时间戳。此前的错误类型可能导致依赖该字段类型的代码无法编译升级后按OptionString使用即可。升级指南从 48.x 平滑迁移到 49.0.0官方为 49.0.0 提供了专门的升级指南docs/source/library-user-guide/upgrading/49.0.0.md本节汇总其中与破坏性变更配套的迁移要点升级 Rust 工具链MSRV 提升到 1.85.1请确保本地工具链不低于该版本当前仓库工作区使用 rust-toolchain.toml 指定的1.98.1。适配 Boxed DataFusionError对ArrowError、SQL、SchemaError三个变体的构造与匹配改为内部Box::new(...)。迁移元数据 API 到FieldMetadataArrowField的元数据此前分别以HashMapString, String和BTreeMapString, String存储现在统一使用FieldMetadata结构更易用也更高效。转换方式let metadata FieldMetadata::from(field); let updated_field metadata.add_to_field(field);迁移字符串映射配置废弃的datafusion.sql_parser.map_varchar_to_utf8view请迁移到map_string_types_to_utf8view默认true。SchemaAdapter系列废弃DataFusion 正在从转换数据SchemaAdapter转向转换表达式本身PhysicalExprAdapterFactory首个落地点是 Parquet 的谓词下推。默认情况下未自定义SchemaAdapterFactory会直接使用表达式转换路径若设置了自定义SchemaAdapterFactory仍会生效但会打印废弃警告。建议实现PhysicalExprAdapterFactory并替换旧接口可参考 datafusion-examples/examples/custom_data_source/default_column_values.rs 中的用法。注意旧代码路径对应的自定义文件 schema 转换能力在 #16791 中得到了恢复与保留。TableParquetOptions补充crypto字段结构体新增加密字段用默认值补齐即可TableParquetOptions { global, column_specific_options, key_value_metadata, crypto: Default::default(), // 新增字段 }Expr::WindowFunction相关升级指南#16313。值得关注的 Bug 修复与内部改进49.0.0 修复了一批与正确性、一致性和稳定性相关的问题以下按主题归类规划器与优化器正确性#16356在eliminate_cross_join规则中保留null_equals_null标志#16465临时修复动态 top-k 优化中的 bug#16641修复 TopK Sort 被错误地下推到带 anti join 的连接之下#16646修复 Parquet 扫描中未尊重 parquet filter pushdown 配置的问题#16560修复JOIN ... USING中列名归一化问题#16454修复物理规划 Join 时重复字段名错误。执行器与表达式#16391修复generate_series/range的错误处理#16342修复空数据流创建文件的问题后在 #16682 回退#16783支持预排序数据源中的可空列#16539修复标量与数组在 decimal→timestamp 转换上的不一致#16759make_date任一参数为 NULL 时返回 NULL#16529array_has对空数组返回 false 而非 NULL#16348修复array_concat对 NULL 数组的处理。SQL 解析与反解析Unparser#16584修复限定列名中的保留关键字问题#16610修复 Unparser 中get_field内嵌套标量函数的支持#16669尝试将普通保留函数降级为列名#16538 与 #16606完善WITHIN GROUP的支持并禁止同时指定order_by与within_group。平台兼容性与构建#16418通过将 sqlparser 的recursive-protection设为可选恢复 WASM 编译支持#16480修复 FFI 分区求值器的列索引问题#16350修复 SparkSha2 的兼容性并支持 Int32。测试与基础设施核心测试持续迁移到 insta 快照框架#16324、#16617SQL 逻辑测试支持--test-threads#16694、#16722tpch 全部查询增加了序列化/反序列化往返测试#16742基准测试新增clickbench_pushdown#16731、topk_tpch#16410等clickbench 查询集拆分为单文件#16476并支持查询过滤#16477。结语Apache DataFusion 49.0.0 是一个在架构层面与性能层面都极具分量的版本Equivalence 系统的重构为后续优化规则奠定了更稳健的基础datafusion-pruning的拆分让模块边界更清晰Parquet 模块化加密将企业级安全能力引入查询引擎而collect_statistics默认开启、字符串视图统一映射、连接与排序热点的加速则让普通用户无需改动即可获得更优的执行计划与运行性能。对于升级使用者而言本文列出的 9 项破坏性变更与 7 条迁移要点覆盖了主要风险面对源码感兴趣的读者可以沿着 datafusion/physical-expr/src/equivalence、datafusion/pruning/src 与 datafusion/common/src/config.rs 三条线索深入阅读 49.0.0 的实现细节。赞分享大数据数据分析后端【免费下载链接】datafusionApache DataFusion SQL Query Engine项目地址https://gitcode.com/gh_mirrors/datafu/datafusion点击查看免费下载相关推荐Apache DataFusion 39.0.0 版本全解析UDF 体系重构、Parquet 统计提取与规划性能优化Apache DataFusion 39.0.0 版本全解析UDF 体系重构、Parquet 统计提取与规划性能优化 Apache DataFusion 39大数据数据分析后端Apache DataFusion 49.0.0 升级指南错误类型 Box 化、Utf8View 统一映射与 Parquet 加密等 7 大变更实战解析Apache DataFusion 49.0.0 升级指南错误类型 Box 化、Utf8View 统一映射与 Parquet 加密等 7 大变更实战解析 Ap大数据数据分析后端Apache DataFusion 45.0.0 版本解析破坏性变更、性能优化与新特性全景解读Apache DataFusion 45.0.0 版本解析破坏性变更、性能优化与新特性全景解读 45.0.0 是 Apache DataFusion 一个里程大数据数据分析后端上一篇一文读懂sysTrace架构AI性能监控工具的核心组件与设计原理 下一篇如何利用RAM-A为AI Agents构建高效内存系统10个核心技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考