在之前的帖子《SparkSql与HiveSql的兼容性——踩过的十大坑》中,我们介绍了HiveSql迁移SparkSQL时踩过的比较典型的十大差异。本文分享下如何在Spark中调用Hive的内置函数,从而屏蔽差异,Spark结果和Hive结果保持一致。
1 思路
经仔细比对,发现Spark内置函数和Hive内置函数在实现上存在差异(今后有时间分享下具体实现有什么不同,从而导致结果不一致?另外,孰对孰错?),这里我们暂且抛开两个引擎孰对孰错,首先由于数仓存量任务都是以Hive为基础引擎运行的,所以这些差异点必须以Hive为准。
那么问题来了,如何修复这个问题呢?
既然内置函数不同,那Spark可否直接调用Hive的内置函数从而屏蔽这个差异呢?答案是肯定的。
破解思路:我们知道Spark也是可以注册用户自定的UDF函数的,那我们如果可以将Hive的内置注册到Spark里,并替换掉Spark自身的内置函数,那么便可实现Spark调用Hive内置函数的功能。
2 修复方案
我们在构建session(可以选择HiveSessionCatalog
或 SparkSession
中)的时候,将Hive的内置函数注册到Spark中,实现如下:
1 | def registerHiveSysFunc(session: SparkSession) = { |
3 测试验证
打包部署新的Spark客户端,验证生效:
1 | 开启开关 |
4 后续的计划
为什么我们花费这么大精力,维护内部自研Spark版本呢?其实这里的差异性由来已久,Spark社区也有很多的讨论。比如对于特殊的日期格式0000-00-00
, 9999-99-99
,Spark的日期函数to_date返回值是NULL,Spark开发者认为非法日期返回NUll是合理的;而Hive返回了一个错误的日期0002-11-30
。所以说没有孰对孰错的定论。
HiveSql迁SparkSql,好多公司都遇到该痛点,后续我们计划将该功能贡献给社区。
本文链接: https://stefanxiepj.github.io/archives/eea63b47.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!