- 批处理
- 流处理
- 大数据
【免费下载链接】beam
Apache Beam is a unified programming model for Batch and Streaming data processing.
本文以 Apache Beam ZetaSQL 官方文档(math-functions.md)为骨架,系统讲解 Beam ZetaSQL 内置数学函数中取模与取整四大家族函数(MOD、CEIL、CEILING、FLOOR)的语法、语义、类型签名与边界行为,并结合 Beam Java SDK 中 ZetaSQL 翻译模块的源码与测试用例,说明这些函数在查询计划阶段的底层映射与执行验证方式。读完本文,你将能准确区分向上取整与向下取整在正负数上的差异、掌握 MOD 结果符号规则,并能在自己的 Beam SQL 管线中正确使用这些函数。
一、Beam ZetaSQL 与数学函数支持概览
Beam SQL 支持 ZetaSQL 语言的一个变体。ZetaSQL 是 Google 开源的分析型 SQL 方言,与 BigQuery 的 SQL 框架语法相近,因此 Beam ZetaSQL 特别适合用于读写 BigQuery 表的管线(参见 overview.md)。Beam ZetaSQL 的翻译实现位于 Java SDK 的sdks/java/extensions/sql/zetasql模块(build.gradle 中描述为 "ZetaSQL to Calcite translator",当前锁定 ZetaSQL 版本2022.04.1):它先将 ZetaSQL 语法解析成 ZetaSQL 的 Resolved AST,再翻译为 Apache Calcite 的关系代数计划,最终交由 Beam 的各执行引擎(Direct、Flink、Spark、Dataflow 等)运行。
在函数支持层面,SupportedZetaSqlBuiltinFunctions.java集中维护了 Beam ZetaSQL 当前支持的内置函数清单(SupportedZetaSqlBuiltinFunctions.java)。文件中被注释掉的条目表示尚未支持,这是判断某个 ZetaSQL 函数能否在 Beam 中直接使用的权威依据。其中 "Math functions" 段落完整覆盖了本文要讲的四个函数:
FN_CEIL_DOUBLE(ceil(double) -> double)与FN_CEIL_NUMERIC(ceil(numeric) -> numeric),FN_CEIL_BIGNUMERIC未启用;FN_FLOOR_DOUBLE与FN_FLOOR_NUMERIC,FN_FLOOR_BIGNUMERIC未启用;FN_MOD_INT64(mod(int64, int64) -> int64)与FN_MOD_NUMERIC(mod(numeric, numeric) -> numeric),FN_MOD_BIGNUMERIC未启用。
同一清单中还包含 ABS、SIGN、ROUND、TRUNC、DIV、IS_INF、IS_NAN、IEEE_DIVIDE、SAFE_ADD/SUBTRACT/MULTIPLY/DIVIDE/NEGATE、SQRT、POW、EXP、LN、LOG10、LOG 以及全套三角函数等数学函数,说明这些取模取整函数只是 Beam ZetaSQL 完整数学函数体系的一部分。
通用规则:NULL 传播语义
原文档明确了一条所有数学函数共用的通用规则:
如果任一输入参数为
NULL,所有数学函数都返回NULL。
也就是说,MOD(NULL, 3)、CEIL(NULL)、FLOOR(NULL)的结果都是NULL而不是报错或返回默认值。这一行为与 SQL 标准的 NULL 传播(null propagation)语义一致,也意味着这些函数不会作为过滤器吞掉含 NULL 的行——结果行的对应字段值为 NULL。
二、MOD:取模运算
MOD(X, Y)功能:返回X除以Y的余数。与原文档一致,Beam ZetaSQL 中MOD的结果符号与X相同(而不是与除数Y相同,这与某些编程语言中的取模定义不同)。
类型签名(依据 SupportedZetaSqlBuiltinFunctions.java):
| 签名 | 说明 | 状态 |
|---|---|---|
MOD(INT64, INT64) -> INT64 | 整数取模,返回 INT64 | ✅ 支持 |
MOD(NUMERIC, NUMERIC) -> NUMERIC | 高精度数值取模 | ✅ 支持 |
MOD(BIGNUMERIC, BIGNUMERIC) -> BIGNUMERIC | 更大范围数值取模 | ❌ 未启用(源码注释) |
底层映射:在查询翻译阶段,ZetaSQL 的函数调用mod会被映射为 Calcite 标准运算符表中的MOD运算符(见 SqlOperatorMappingTable.java),随后由 Calcite 的 SQL 执行器按该运算符语义求值。
测试验证(ZetaSqlMathFunctionsTest.java):
// INT64 类型:MOD(4, 2) = 0 String sql = "SELECT MOD(4, 2)"; // 期望结果:Row 中 f_int64 = 0L// NUMERIC 类型:MOD(NUMERIC '1.23456e05', NUMERIC '5') = 1 String sql = "SELECT MOD(NUMERIC '1.23456e05', NUMERIC '5')"; // 期望结果:BigDecimal 值 "1"易混淆点:MOD与同清单中的DIV(整除)是对偶关系——DIV(X, Y)返回整除的商,MOD(X, Y)返回余数,二者配合可以完成 "商 + 余数" 的整数分解计算。
三、CEIL / CEILING:向上取整
CEIL(X) CEILING(X)功能:CEIL(X)返回不小于X的最小整数值,结果类型为FLOAT64;CEILING(X)是CEIL(X)的同义词,二者行为完全等价,可互换使用。
类型签名(依据 SupportedZetaSqlBuiltinFunctions.java):
| 签名 | 说明 | 状态 |
|---|---|---|
CEIL(DOUBLE) -> DOUBLE | 双精度浮点向上取整 | ✅ 支持 |
CEIL(NUMERIC) -> NUMERIC | NUMERIC 向上取整 | ✅ 支持 |
CEIL(BIGNUMERIC) -> BIGNUMERIC | — | ❌ 未启用(源码注释) |
底层映射:ceil在 SqlOperatorMappingTable.java 中被映射为 Calcite 的SqlStdOperatorTable.CEIL;由于CEILING是CEIL的同义词,ZetaSQL 解析层会在函数签名解析阶段统一处理,两者最终走向相同的 Calcite 运算符。
测试验证(ZetaSqlMathFunctionsTest.java):
// FLOAT64 类型:CEIL(1.2) = 2.0,CEIL(-1.2) = -1.0 String sql = "SELECT CEIL(1.2), CEIL(-1.2)"; // 期望结果:2.0, -1.0// NUMERIC 类型:CEIL(NUMERIC '1.23456e04') = 12346,CEIL(NUMERIC '-1.23456e04') = -12345 String sql = "SELECT CEIL(NUMERIC '1.23456e04'), CEIL(NUMERIC '-1.23456e04')";注意负数场景:CEIL(-1.2) = -1.0,因为 -1.0 是"不小于 -1.2"的最小整数(-1 > -1.2);而CEIL(-2.3) = -2.0,同理。
四、FLOOR:向下取整
FLOOR(X)功能:FLOOR(X)返回不大于X的最大整数值,结果类型为FLOAT64。
类型签名(依据 SupportedZetaSqlBuiltinFunctions.java):
| 签名 | 说明 | 状态 |
|---|---|---|
FLOOR(DOUBLE) -> DOUBLE | 双精度浮点向下取整 | ✅ 支持 |
FLOOR(NUMERIC) -> NUMERIC | NUMERIC 向下取整 | ✅ 支持 |
FLOOR(BIGNUMERIC) -> BIGNUMERIC | — | ❌ 未启用(源码注释) |
底层映射:floor在 SqlOperatorMappingTable.java 中被映射为 Calcite 的SqlStdOperatorTable.FLOOR。
测试验证(ZetaSqlMathFunctionsTest.java):
// FLOAT64 类型:FLOOR(1.2) = 1.0,FLOOR(-1.2) = -2.0 String sql = "SELECT FLOOR(1.2), FLOOR(-1.2)"; // 期望结果:1.0, -2.0// NUMERIC 类型:FLOOR(NUMERIC '1.23456e04') = 12345,FLOOR(NUMERIC '-1.23456e04') = -12346 String sql = "SELECT FLOOR(NUMERIC '1.23456e04'), FLOOR(NUMERIC '-1.23456e04')";注意负数场景:FLOOR(-1.2) = -2.0,因为 -2.0 是"不大于 -1.2"的最大整数(-2 < -1.2);FLOOR(-2.3) = -3.0,FLOOR(-2.8) = -3.0。
五、CEIL 与 FLOOR 行为对照(官方示例)
原文档给出了 Cloud Dataflow SQL 取整函数行为示例表,完整覆盖了正数、负数、整数边界与零值,是理解向上/向下取整差异的最佳速查表:
| 输入 "X" | CEIL(X) | FLOOR(X) |
|---|---|---|
| 2.0 | 2.0 | 2.0 |
| 2.3 | 3.0 | 2.0 |
| 2.8 | 3.0 | 2.0 |
| 2.5 | 3.0 | 2.0 |
| -2.3 | -2.0 | -3.0 |
| -2.8 | -2.0 | -3.0 |
| -2.5 | -2.0 | -3.0 |
| 0 | 0 | 0 |
从表中可以提炼三条规律:
- 正数区间:
CEIL向"正无穷"方向进位(2.3 → 3.0),FLOOR向"零"方向截断(2.8 → 2.0),二者只在输入恰为整数(如 2.0)时结果一致; - 负数区间:方向恰好反转——
CEIL(-2.3) = -2.0(向零靠拢),FLOOR(-2.3) = -3.0(远离零);这也是"不小于 X 的最小整数 / 不大于 X 的最大整数"定义的直接推论; - 零值:
CEIL(0) = 0、FLOOR(0) = 0,取整不改变符号与数值。
因此,若业务需要"四舍五入"式的对称行为,应使用同清单中的ROUND(X[, digits])函数(支持ROUND(double)、ROUND(double, int64)、ROUND(numeric)、ROUND(numeric, int64)等签名,见 SupportedZetaSqlBuiltinFunctions.java),而不要用CEIL/FLOOR。
六、类型系统与算术运算符的配合
Beam ZetaSQL 的数值类型体系中(详见>SELECT CEIL(price / 10.0) * 10 AS rounded_up, MOD(CAST(price AS INT64), 10) AS remainder FROM orders;
七、在 Beam 管线中验证这些函数
Beam ZetaSQL 的测试基础设施(ZetaSqlTestBase.java)展示了验证 SQL 行为的标准流程,也可作为你自行实验的模板:
- 通过
JdbcDriver.connect(createBeamTableProvider(), PipelineOptionsFactory.create())建立 JDBC 会话并注册测试表(如table_with_numeric); - 用
Frameworks.newConfigBuilder()结合ZetaSQLQueryPlanner.getZetaSqlRuleSets()构建查询规划配置; - 用
ZetaSQLQueryPlanner(config).convertToBeamRel(sql)将 SQL 转为 Beam 关系节点; - 用
BeamSqlRelUtils.toPCollection(pipeline, beamRelNode)把计划物化为PCollection<Row>; - 用
PAssert.that(stream).containsInAnyOrder(...)断言输出行,并pipeline.run().waitUntilFinish()执行。
ZetaSqlMathFunctionsTest 正是沿这条链路为 INT64、FLOAT64、NUMERIC 三种类型分别验证了本文全部函数的数值结果(除上文列出的用例,还包括算术运算符、ABS、SIGN、ROUND、TRUNC、DIV、SAFE_* 系列、SQRT、POW、EXP、LN、LOG10、LOG、三角函数等,见 ZetaSqlMathFunctionsTest.java 全文)。你可以将SELECT中的表达式替换为自己的业务计算,把该测试类作为"SQL 语义的即插即用验证台"。
八、使用建议与限制说明
- NULL 传播:所有数学函数对 NULL 输入返回 NULL,设计 CASE 分支或 COALESCE 时需留意;
- BIGNUMERIC 不支持:
MOD、CEIL、FLOOR的 BIGNUMERIC 签名在 SupportedZetaSqlBuiltinFunctions.java 中均为注释状态,超出 NUMERIC 精度范围的运算请改用 NUMERIC 或拆分为 FLOAT64 处理; - 取整方向:
CEIL/FLOOR并非四舍五入;需要按小数位舍入请使用ROUND(X, digits),需要直接截断小数请使用TRUNC(X, digits); - 与 BigQuery 的兼容性:由于 ZetaSQL 与 BigQuery SQL 同源,在 Beam ZetaSQL 中写
MOD/CEIL/FLOOR的经验可直接迁移到使用 BigQueryIO 的读写作业(见 overview.md)。
如需了解函数调用规则、词法与语法细节,可继续阅读同目录下的 syntax.md、lexical.md 与 operators.md。
- 批处理
- 流处理
- 大数据
【免费下载链接】beam
Apache Beam is a unified programming model for Batch and Streaming data processing.
相关推荐
Apache Beam ZetaSQL 数学函数(MOD、CEIL、CEILING、FLOOR)完整参考指南
Apache Beam ZetaSQL 数学函数(MOD、CEIL、CEILING、FLOOR)完整参考指南 本文是 Apache Beam ZetaSQL 方
大数据批处理流处理数据工程Apache Beam ZetaSQL 字符串函数完全指南:CHAR_LENGTH 到 TRIM 的语法、语义与源码实现
Apache Beam ZetaSQL 字符串函数完全指南:CHAR_LENGTH 到 TRIM 的语法、语义与源码实现 本篇技术指南基于 string fun
大数据批处理流处理数据工程OneUptime VMware Monitor 实战指南:基于 OpenTelemetry 全面监控 vSphere 环境
OneUptime VMware Monitor 实战指南:基于 OpenTelemetry 全面监控 vSphere 环境 本指南围绕 OneUptime 的
批处理流处理大数据
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考