SparkSQL踩坑

在开发中,遇到了一个奇怪的Join结果。简化之后的模型如下,目测执行的结果第一个为true,第二个为false,而实际的结果却是两个True。

1
2
3
4
5
6
7
8
9
10
11
create or replace temp view test1 as
select
'23843968833490313' as s1
, cast('23843968833490313' as decimal(18,0)) as s2
, cast('23843968833490312' as decimal(18,0)) as s4
;
select
s1 = s2
, s1 = s4
from test1
;

究其原因是在不同类型的比较中,Spark会把其先转为Double类型再进行比较,而Double类型的精度有限,这样就会出现让人匪夷所思的现象。在实际复杂的Join中,往往会忽视数据类型的检查。

所以在实际开发中,一定要保证join两边的数据类型一致,特别是join条件两边存在表达式的情况,例如:

1
2
3
4
from tableA 
left join tableB
on coalesce(tableA.id1 , tableA.id2) = tableB.id
;

建议写成:

1
2
3
4
from tableA 
left join tableB
on cast(coalesce(tableA.id1 , tableA.id2) AS decmial(18,0)) = tableB.id
;

在有表达式的地方,加上类型转换。

如果能在建表之初,根据业务含义和开发规范合适的选择字段的类型,则可以在很大程度上避免这类情况的发生。

比如xxx_ID 统一使用Decimal(位数,0) ,xxFlag统一使用Boolean等,而不是String和这类情况混用。