尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

StarRocks `negative()` 数学函数详解:语法、数据类型支持与向量化实现原理

StarRocks `negative()` 数学函数详解:语法、数据类型支持与向量化实现原理 StarRocksnegative()数学函数详解语法、数据类型支持与向量化实现原理【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocksnegative()是 StarRocks 提供的一元数学函数用于返回输入参数的相反数即对数值取负。本指南以 negative.md 文档为骨架完整讲解其语法、参数类型、返回值与实操示例并结合 BEbe/src/exprs/math_functions.h与 FEfe/fe-core/src/main/java/com/starrocks/catalog/FunctionSet.java等的源码实现深入说明它在向量化执行、DECIMAL 类型推导与统计信息估算中的底层机制。阅读完本文你将能在 SQL 中正确、高效地使用negative()并理解它与一元负号运算在优化器层面的联动关系。函数简介返回输入参数的相反数negative(arg)是 StarRocks 数学函数家族中的一元函数语义等价于对参数执行一元取负运算-arg但与直接使用负号不同它作为显式函数调用可出现在 SELECT 列表、WHERE 条件、JOIN 关联表达式等任意 SQL 位置并被 FE 优化器识别为单调递减函数参与表达式推导详见下文与优化器的联动章节。该函数是严格一元函数strict unary function——输入为单个数值输出与输入保持完全相同的数据类型不会发生隐式类型转换或精度损失。语法negative(arg)该函数只接受一个参数返回其相反数。语法形式与 StarRocks 其他一元数学函数如positive()、abs()保持一致。参数说明与支持的数据类型arg支持以下六种数值数据类型数据类型说明BIGINT64 位有符号整数DOUBLE双精度浮点数DECIMALV2StarRocks 的旧版高精度定点小数类型最大精度 27基于int128_t存储DECIMAL32定点小数类型基于 32 位存储DECIMAL V3 系列DECIMAL64定点小数类型基于 64 位存储DECIMAL V3 系列DECIMAL128定点小数类型基于 128 位存储DECIMAL V3 系列从参数列表可以看出negative()的设计刻意覆盖了 StarRocks 的整数BIGINT、浮点DOUBLE与全部定点小数DECIMAL 家族数值类型使其可以安全地作用于任意数值列而无需提前转换类型。返回值返回与输入arg相同数据类型的值即输入为BIGINT返回BIGINT相反数输入为DOUBLE返回DOUBLE相反数输入为DECIMALV2/DECIMAL32/DECIMAL64/DECIMAL128返回同精度、同小数位的定点小数相反数。这意味着在使用negative()对定点小数列取负时不会破坏列的精度与 scale计算结果可直接写回同类型目标列。使用示例以下是官方文档给出的两个典型示例来自 negative.md。示例一对 BIGINT 取负mysql select negative(3); ------------- | negative(3) | ------------- | -3 | ------------- 1 row in set (0.00 sec)示例二对 DECIMALV2 取负mysql select negative(cast(3.14 as decimalv2)); -------------------------------------- | negative(CAST(3.14 AS DECIMAL(9,0))) | -------------------------------------- | -3.14 | -------------------------------------- 1 row in set (0.01 sec)第二个示例展示了negative()与 DECIMAL 类型配合的典型用法先将浮点字面量3.14显式转换为 DECIMAL 类型再通过negative()得到-3.14结果完整保留了小数部分。这在实际业务中对应将金额、单价等定点小数列整体取负如冲销、退款的常见场景。结合 BE 源码看向量化实现统一的严格一元函数模板negative()的 BE 端实现位于 math_functions.h采用模板化向量化函数定义template LogicalType Type DEFINE_VECTORIZED_FN(negative) { if constexpr (lt_is_decimalType) { const auto type context-get_return_type(); return VectorizedStrictUnaryFunctionnegativeImpl::evaluateType(VECTORIZED_FN_ARGS(0), type.precision, type.scale); } else { return VectorizedStrictUnaryFunctionnegativeImpl::evaluateType(VECTORIZED_FN_ARGS(0)); } }核心实现逻辑可以拆解为两点向量化批处理函数通过VectorizedStrictUnaryFunction模板对整列数据Column进行批量运算而不是逐行解释执行充分发挥 StarRocks 向量化执行引擎SIMD 友好、缓存友好的性能优势。DECIMAL 特化分支当输入是 DECIMAL 系列类型lt_is_decimalType为真时会额外传入返回类型的precision精度与scale小数位确保定点小数取负后保持原有的精度与 scale 元信息非 DECIMAL 类型BIGINT、DOUBLE则走无精度参数的简化路径。真正的取负运算取负的数学运算本身定义在 math_functions.h 中实现极其简洁// negative DEFINE_UNARY_FN_WITH_IMPL(negativeImpl, v) { return -v; }即对每一个元素直接执行一元取负运算-v。这也印证了negative()在语义上就是逐元素的相反数没有任何近似或舍入逻辑——这正是它能对 DECIMAL 类型保持精确的原因。与positive()的对称设计在 math_functions.h 中positive()的实现是直接返回输入列std::move(*columns[0]).mutate()即原样透传而negative()则真正执行取负。两者共同构成 StarRocks 对一元正负号运算的函数化封装便于优化器统一识别与推导。前端 FE 中的注册、类型推导与统计信息函数注册negative是 StarRocks 内置函数在 FE 侧通过常量 FunctionSet.NEGATIVE 登记函数名并作为一元数学函数注册进内置函数表供 SQL 解析与绑定阶段按名称解析。DECIMAL 类型保持在 DecimalV3FunctionAnalyzer.java 中NEGATIVE被归入DECIMAL_UNARY_FUNCTION_SETpublic static final SetString DECIMAL_UNARY_FUNCTION_SET new ImmutableSortedSet.Builder(String::compareTo) .add(FunctionSet.ABS).add(FunctionSet.POSITIVE).add(FunctionSet.NEGATIVE) .add(FunctionSet.MONEY_FORMAT).add(FunctionSet.MATERIALIZE).build();这组函数被 FE 识别为一元且不改变类型的 DECIMAL 函数在类型分析阶段保证negative(decimal_col)的结果类型仍为 DECIMAL且精度、scale 与原列一致与 BE 端传入precision/scale的特化实现前后呼应。这也是文档中返回与输入相同数据类型这一规则在类型系统层面的落地保证。统计信息区间反转在优化器的统计估算模块 ExpressionStatisticCalculator.java 中NEGATIVE表达式的取值区间按如下规则推导case FunctionSet.NEGATIVE: double negativeMinValue -minValue; double negativeMaxValue -maxValue; minValue Math.min(negativeMinValue, negativeMaxValue); maxValue Math.max(negativeMinValue, negativeMaxValue); break;即对输入列的 [min, max] 区间取负后重新排序作为输出区间。由于取负会反转大小关系-max变成最小值、-min变成最大值代码用Math.min/Math.max重新规整边界。这一区间推导让优化器能够对negative(col)参与过滤或 JOIN 的场景做出更准确的行数估算从而选择更优的执行计划。与优化器的联动单调递减与 Runtime Filternegative()在优化器中还被识别为单调递减函数。在 ExpressionStatisticCalculator.java 附近的注释中明确写有NEGATIVE(x): exact -x, fixed-point only对定点数精确取负NEGATIVE(x): y -x (monotonic decreasing) [l,u] - [-u,-l], reverse order单调递减区间由 [l,u] 映射为 [-u,-l] 并反转顺序。单调性信息直接服务于Runtime Filter 表达式推导与 Join 谓词下推。仓库的 SQL 回归测试 test_runtime_filter_monotonic_expr 中就有对应的 JOIN 场景select p.id, b.id from rf_expr_probe_${uuid0} p join rf_expr_build_${uuid0} b on p.c_bigint * -1 b.k_negative order by p.id, b.id;该用例验证了c_bigint * -1语义等价于negative(c_bigint)的负号形式能够作为单调表达式参与 Runtime Filter 的构建与探测从而在 JOIN 执行时通过过滤下推减少数据传输量、提升查询性能。测试验证DECIMAL 精确取负negative()的正确性由 BE 单元测试覆盖。在 math_functions_test.cpp 的NegativeDecimalTest中输入3333333333.2222222222断言结果为-3333333333.2222222222输入740740740.716049断言结果为-740740740.716049。该测试直接以DecimalColumn构造 DECIMALV2 列并调用MathFunctions::negativeTYPE_DECIMALV2验证了 BE 端向量化实现对高精度定点小数取负的逐位精确性27 位精度下无任何精度损失与文档中 DECIMALV2 的声明完全一致。总结negative()是一个看似简单、但设计严谨的一元数学函数使用层面接受BIGINT、DOUBLE及 DECIMAL 家族六种数值类型返回类型与输入完全一致适用于金额冲销、坐标取反、区间镜像等业务场景实现层面BE 通过 math_functions.h 的negativeImpl即return -v配合严格一元向量化模板批量执行DECIMAL 类型携带 precision/scale 确保精确取负优化层面FE 在 DecimalV3FunctionAnalyzer.java 中保证类型不变并在 ExpressionStatisticCalculator.java 中做区间反转统计与单调递减推导进而支撑 Runtime Filter 等查询优化。掌握这些细节后你可以在 StarRocks 中放心地将negative()用于任意数值列并理解它在执行计划中的优化路径。如需查看更多数学函数可参考 数学函数文档目录 及同目录下的其他函数说明。【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表