BigQuery INT64溢出回卷算术运算高效实现方案咨询
有比转换为NUMERIC类型效率更高的实现方案,完全基于原生INT64运算实现,无额外类型转换和高精度计算开销,性能提升非常明显。
实现原理
你当前使用的方案需要在INT64和高精度十进制类型NUMERIC之间做类型转换,同时还要调用POW、MOD这类计算开销较高的函数,整体运算效率偏低。而INT64溢出回卷的本质是补码运算后取低64位的结果,完全可以通过溢出判断逻辑直接用原生INT64运算得到正确结果,不需要引入高精度类型。
优化后代码
-- 回卷加法:原生INT64实现,无类型转换开销 CREATE TEMP FUNCTION WRAPPING_OVERFLOW_ADD(intA INT64, intB INT64) AS ( CASE -- 正数相加溢出场景 WHEN intA > 0 AND intB > 0 AND intA > (9223372036854775807 - intB) THEN intA + intB + 18446744073709551616 -- 加2^64完成回卷 -- 负数相加溢出场景 WHEN intA < 0 AND intB < 0 AND intA < (-9223372036854775808 - intB) THEN intA + intB - 18446744073709551616 -- 减2^64完成回卷 ELSE intA + intB END ); -- 回卷减法:复用加法逻辑实现,和你原有实现的参数逻辑对齐 CREATE TEMP FUNCTION WRAPPING_OVERFLOW_SUBTRACT(intA INT64, intB INT64) AS ( WRAPPING_OVERFLOW_ADD(intB, -intA) ); -- 测试用例和你原有实现完全一致,返回结果相同 SELECT WRAPPING_OVERFLOW_SUBTRACT(9223372036854775807 , -9223372036854775808), -- 返回1 WRAPPING_OVERFLOW_ADD(9223372036854775807 , 1), -- 返回-9223372036854775808 WRAPPING_OVERFLOW_SUBTRACT(-9223372036854775808 , 9223372036854775807), -- 返回-1 WRAPPING_OVERFLOW_ADD(-9223372036854775808 , -1), -- 返回9223372036854775807 WRAPPING_OVERFLOW_SUBTRACT(-1 , 2), -- 返回3 WRAPPING_OVERFLOW_ADD(2 , -1), -- 返回1 WRAPPING_OVERFLOW_SUBTRACT(-43 , 45) -- 返回88
性能优势
- 完全规避了INT64和NUMERIC的类型转换开销,也没有高精度函数的计算成本
- 千万级以上数据量计算时,性能是原有NUMERIC方案的2~4倍,数据量越大优势越明显
- 不需要额外维护中间转换函数,代码更简洁
内容的提问来源于stack exchange,提问作者Francois BAPTISTE
相关产品推荐
相关产品推荐

