ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Apache Arrow Acero 的 Substrait 支持:用标准执行计划驱动 C++ 流式计算引擎

Apache Arrow Acero 的 Substrait 支持:用标准执行计划驱动 C++ 流式计算引擎 Apache Arrow Acero 的 Substrait 支持用标准执行计划驱动 C 流式计算引擎【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow导读本文围绕 Apache Arrow C 文档 Using Acero with Substrait 展开系统介绍 Acero 作为 Substrait consumer消费端的能力边界从执行计划的基本概念、Substrait 版本要求到各关系Relation、表达式、字面量、类型与函数的完整符合性清单Conformance并深入 cpp/src/arrow/engine/substrait 源码说明DeserializePlan/SerializePlan等 API 的实际用法、扩展点ExtensionProvider、NamedTableProvider以及类型映射等底层机制。读完本文你将掌握如何为 Acero 构造可被接受的 Substrait 计划、理解哪些特性会被拒绝以及如何通过自定义扩展接口把计划落地到自己的数据源。注意Acero 仍处于实验阶段稳定 API 尚不保证见 Acero 总览Substrait 相关 API 同样标注为 EXPERIMENTAL见 api.h。为什么用 Substrait 描述执行计划在 Arrow C 中Acero 是一个流式查询执行引擎它消费零个或多个输入数据流产出一个输出数据流计算以执行计划ExecPlan的形式表达。Acero 拥有自己的内部计划表示但文档明确建议大多数用户不要直接与之交互否则代码会与 Acero 强耦合。Substrait 是执行计划的开放标准。Acero 实现了 Substrait 的 consumer 接口——即 Acero 可以接收一份 Substrait 计划并完成它加载所需数据、执行所需计算。采用 Substrait 计划的好处是用户可以随时切换到底层不同的执行引擎只要对方同样支持 SubstraitSubstrait producer 生态提供了大量友好的高层 API例如 ibis-substrait 这类工具可从 Python 表达式生成计划无需手写复杂的关系图未来基于 Substrait 的优化器/规划器工具可以直接复用。Acero 的用户指南 user_guide.rst 同样把 Substrait 列为创建计划的首选机制。生产端producer负责把用户的查询翻译成 Substrait 计划Acero 作为消费端负责执行——这正是 Acero 的定位专注执行不做优化器。核心 API 一览Substrait 相关的 C API 集中在arrow::engine::substrait命名空间头文件统一入口为 cpp/src/arrow/engine/substrait/api.h主要分为序列化、反序列化与选项三类。反序列化把 Substrait 计划变成可执行计划srde.h即 serde.h提供如下入口函数用途DeserializePlan(buf, ...)反序列化单关系 Substrait Plan返回std::shared_ptracero::ExecPlan结果交给调用方提供的SinkNodeConsumer消费也有返回PlanInfo即Declaration形式的根声明的重载可直接配合DeclarationToXyz方法使用DeserializePlans(buf, ...)反序列化多顶层关系的 Plan返回std::vectoracero::Declaration每个顶层关系对应一个声明DeserializeRelation(buf, ext_set, ...)反序列化单个Rel消息为ExecNode声明DeserializeExpression/DeserializeExpressions反序列化 Substrait 表达式为arrow::compute::Expression/BoundExpressionsDeserializeType/DeserializeSchema反序列化 Substrait 类型 /NamedStruct为 Arrow 类型 / schema这些函数普遍接受ExtensionIdRegistry*默认注册表、ExtensionSet*返回计划使用的扩展映射与ConversionOptions三个可选参数。测试代码中的典型调用形如 serde_test.cc 中的DeserializePlan(*buf, acero::NullSinkNodeConsumer::Make())。序列化把 Acero 计划导出为 SubstraitSerializePlan(declaration, ext_set, conversion_options)把一个 AceroDeclaration作为 sink 关系序列化为二进制 protobuf Substrait 消息SerializeRelation、SerializeExpression、SerializeType、SerializeSchema分别对应关系、表达式、类型与 schema 的导出。内部还提供了两个调试利器SubstraitFromJSON(type_name, json, ignore_unknown_fields true)把 JSON 形式的 Substrait 消息转为二进制 protobuf便于手工构造测试计划SubstraitToJSON(type_name, buf)把二进制消息转回 JSON 便于阅读。转换选项与扩展点options.h 定义了ConversionOptions控制 Substrait 与 Acero 表示之间的转换行为strictnessConversionStrictness枚举取值EXACT_ROUNDTRIP要求无损往返主要用于测试调试、PRESERVE_STRUCTURE尽力用输出端原语建模输入端原语、BEST_EFFORT在保持结构的基础上优先性能是实际使用中最常用的选项也是默认值named_table_providerNamedTableProvider为计划中的具名表提供Declaration的策略默认行为是对含具名表关系的计划返回无效状态named_tap_providerNamedTapProvider用于获取 tap 声明的策略默认返回错误extension_providerExtensionProvider实现负责为 Arrow 未知的关系提供声明默认行为只服务于 Arrow 已知关系allow_arrow_extensions是否允许 Arrow 特有的类型与函数置为false可提高与非 Arrow 引擎的兼容性。ExtensionProvider是文档特别提到的高级扩展入口见 options.h继承该类并实现MakeRel即可为自定义关系类型生成声明并通过set_default_extension_provider全局替换默认实现。Substrait 符合性Conformance详解Substrait 定义了极其广泛的操作符与函数集合Acero 不可能完整支持全部。文档以下列清单界定了当前已实现的功能与各种注意点未列出的关系一律不被支持会导致计划被拒绝。计划Plans与扩展Extensions一份计划应当只有一个顶层关系relation.h 中PlanInfo.root即对应这一约束同时兼容部分 producer 直接使用简单Rel而非RelRoot的情况consumer 当前基于Substrait 0.20.0 版本实现任何更新版本引入的特性都不被支持由于 0.20.0 存在破坏性变更早于 0.20.0 的计划会被拒绝计划若包含任何**扩展类型变体extension type variations**会被拒绝高级扩展可通过自定义arrow::engine::ExtensionProvider实现提供见上文扩展点说明。读取关系Read Relations读取关系是计划的数据入口约束最细projection属性不支持含该属性的计划被拒绝VirtualTable与ExtensionTable两种读取类型不支持目前仅支持parquet 与 arrow 两种文件格式所有 URI 必须使用filescheme即本地文件partition_index、start、length不支持含非默认值的计划被拒绝关于 filter 的重要提示Substrait 规范要求读取关系必须完全满足其 filter但 Acero 只用读取 filter 做投影下推pushdown projection未必完全满足。因此文档建议用户一般应在读取关系之后再附加一个携带相同过滤表达式的 Filter 关系以保证语义正确。这与 Acero 用户指南中 scan 节点过滤发生在两处的说明见 user_guide.rst 中scan一节是一致的。过滤 / 投影 / 连接关系Filter、Project 关系无已知注意事项Join 关系JOIN_TYPE_SINGLE不支持含此类型的计划被拒绝连接表达式必须是调用equal或is_not_distinct_from函数且两个参数都必须为直接引用direct references只支持单一连接键post_join_filter属性不支持会被忽略。聚合关系Aggregate Relations最多支持一个分组集grouping set每个分组表达式必须是直接引用每个度量measure的参数必须是直接引用度量不允许带 filter度量不允许带 sorts度量的调用必须是AGGREGATION_INVOCATION_ALL或AGGREGATION_INVOCATION_UNSPECIFIED度量的阶段phase必须是AGGREGATION_PHASE_INITIAL_TO_RESULT。表达式ExpressionsSubstrait 规范允许在 Filter/Project 关系之外如连接表达式、聚合分组集使用表达式。Acero 通常期望这些表达式是直接引用因此规划器应在把计划交给 Acero 之前将隐式投影提取为正式的 Project 关系。字面量Literals带**非默认可空性non-default nullability**的字面量会导致计划被拒绝。Substrait / Arrow 类型映射表Acero 并未完整支持非空类型可能在不拒绝的情况下允许输入含 null。下表是当前支持的 Substrait 类型类到 Arrow 类型的完整映射来自 substrait.rst 的 list-tableSubstrait 类型Arrow 类型注意事项booleanbooleani8int8i16int16i32int32i64int64fp32float32fp64float64stringstringbinarybinarytimestamptimestampMICRO,timestamp_tztimestampMICRO,UTCdatedate32DAYtimetime64MICROinterval_year—暂不支持interval_day—暂不支持uuid—暂不支持FIXEDCHARL—暂不支持VARCHARL—暂不支持FIXEDBINARYLfixed_size_binaryLDECIMALP,Sdecimal128P,SSTRUCTT1...TNstructT1...TNArrow struct 字段无名称空字符串NSTRUCTN:T1...N:Tn—暂不支持LISTTlistTMAPK,VmapK,VK 不能为可空需要提醒日期/时间相关映射存在精度与语义细节例如timestamp固定映射为微秒精度且无时区timestamp_tz映射为 UTC 时区的微秒时间戳——在跨引擎交换计划时应注意这些约定避免时区或精度信息丢失。函数支持与扩展函数机制文档在函数一节给出了三点重要约束溢出控制Acero 不支持SATURATE溢出选项变参限制对and、or、xor三个函数Acero 不支持接受超过两个参数的 kernel函数 URI 约定Substrait 尚未明确标准函数的 URI 形式。Acero 期望 URI 指向 Substrait 官方main分支上的扩展文件例如算术函数文件应写为https://github.com/substrait-io/substrait/blob/main/extensions/functions_arithmetic.yaml形式注意这是 Substrait 生态的约定 URI仅供理解函数锚点解析规则非仓库内链接。Arrow 专属扩展函数Acero 有一批尚未加入或永远不会加入Substrait 官方函数集的自有函数。要调用它们可使用特殊 URIurn:arrow:substrait_simple_extension_function该常量在源码中定义为kArrowSimpleExtensionFunctionsUri见 extension_set.h。当计划中出现这个 URI 时Acero 只按函数名匹配并忽略所有函数选项options。文档还指出也可以把 URI 完全留空此时 Acero 同样只按函数名匹配。但这一回退机制非标准应视为已弃用优先使用上述特殊 URI。实战建议如何写出能被 Acero 接受的 Substrait 计划综合文档与源码可以总结出面向 Acero 的 plan 编写清单版本对齐确保计划基于 Substrait 0.20.0 生成既不要用更旧的会被拒绝也不要用更新的特性单顶层关系保证计划只有一个顶层关系读取层使用file://scheme 的 parquet/arrow 文件不要使用projection、VirtualTable、ExtensionTable也不要设置非默认的partition_index/start/length如需过滤在 read 之后显式附加 Filter 关系连接层只用单键的equal/is_not_distinct_from连接避开JOIN_TYPE_SINGLE与post_join_filter聚合层单分组集、直接引用分组键与度量参数、无过滤/排序、调用方式为AGGREGATION_INVOCATION_ALL/UNSPECIFIED、阶段为AGGREGATION_PHASE_INITIAL_TO_RESULT类型层只用上表所列类型组合避免 interval_year/interval_day/uuid/FIXEDCHAR/VARCHAR/NSTRUCT 以及可空 MAP 键字面量保持默认可空性函数层标准函数使用官方扩展文件 URIArrow 自有函数使用urn:arrow:substrait_simple_extension_function避免SATURATE与超过两个参数的逻辑函数扩展层若需要计划外的关系类型实现ExtensionProvider并通过ConversionOptions.extension_provider注入具名表需要通过NamedTableProvider提供声明否则默认行为会报错。源码中的验证与测试仓库中与本文档配套的测试与实现可直接佐证上述符合性约束serde_test.cc覆盖DeserializePlan/SerializePlan/DeserializeExpressions等核心往返路径测试中大量使用SubstraitFromJSON手工构造计划function_test.cc验证函数 URI 解析与调用映射包括通过DeserializePlan执行含扩展函数的计划extension_set.cc实现ExtensionSet管理函数/类型的扩展锚点anchor与 URI 解析是类型映射与函数匹配的底层核心test_plan_builder.h测试专用的计划构造辅助可参考其写法理解各关系在 protobuf 层面的形态。如果你想亲手体验最直接的方式是在构建了arrow-engineSubstrait 支持的 Arrow C 环境下用SubstraitFromJSON构造一份符合上述约束的 JSON 计划再调用DeserializePlan配合NullSinkNodeConsumer或自定义SinkNodeConsumer执行参考 serde_test.cc 的用法。小结Acero 对 Substrait 的支持遵循消费端哲学严格限定在 0.20.0 版本范围内对读取、连接、聚合等关系施加明确约束同时通过ExtensionProvider、NamedTableProvider与urn:arrow:substrait_simple_extension_function提供了面向 Arrow 生态的扩展通道。理解这份符合性清单是让 Substrait producer 与 Acero 顺利对接、避免计划被静默拒绝的前提配合 serde.h 的序列化/反序列化 API你既可以把外部计划送入 Acero 执行也可以把 Acero 计划导出为标准格式实现跨引擎的可移植执行。【免费下载链接】arrowApache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory analytics项目地址: https://gitcode.com/GitHub_Trending/arrow3/arrow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表