文章目录
Hive 设计之初,就被定位一款离线数仓产品,虽然Hortonworks喊出了Make Apache Hive 100x Faster的牛逼口号,也在上面做了大量的优化,然而性能提升依旧不大。
而随着OPPO数据量一步步的增多,动辄运行几个小时的hive再也满足不了交互查询的需求,因此我们引入了presto,sql on hadoop阵营里的优秀代表。主要适用于即席查询。
然而事情往往木有那么简单,很多分析师用惯了hql,迁移的成本很大,所以本着业务方都是美丽的上帝的原则。为了使用户能平滑的将业务迁移到presto上,我们义无反顾跳入了presto兼容hive这个大坑中,接下来介绍下我们主要兼容工作。
presto兼容hive,总的来说需要解决如下几点问题:
- hive的udf;
- hive视图;
- 语义处理上的不同,如presto中1/2=0, hive中为0.5。
要完全解决这些问题无疑是费时费力,所以我们在presto和hive之上构建一层路由层--功能是将查询请求优先提交到presto中查询。若执行错误,则路由到hive中。
当然还是存在一定风险,因为由于语义处理上的不同,相同的sql在presto和hive中可能会得到不同的结果。
语义上的修改
Part 1: Key not present in map
presto处理map,若key不存在,会报错,而hive会返回null。
presto> SELECT m[3] from (select map(ARRAY[1, 3], ARRAY[2, 4]) as m); _col0 ------- NULL (1 row)
Part 2: Cast as string
由于presto中并没有名为string的类型,出现若进行cast as string这样的转换,或者表定义中有string类型会出现Unknown type 的错误。因此我们在ASTBuilder.java中把string替换为了varchar类型(实现了对sql语法树的转换)
Part 3: 类型隐式转换
迁移过程中,在presto中经常会出现类型不匹配的错误。核心原因就是hive会对数据类型做兼容性转换。一开始考虑对运算符进行重载,如添加以下函数:
@ScalarOperator(EQUAL) @SqlType(StandardTypes.BOOLEAN) public static boolean equal(@SqlType(StandardTypes.BIGINT) long left, @SqlType(StandardTypes.VARCHAR) Slice right) { return left == Long.valueOf(right.toStringUtf8()); }
就能支持如下case:
presto> select 1 = '1' _col0 ------- true (1 row)
然而这种方式需要对+,- ,* ,/ ,between ,in 等几乎所有的运算符进行重载,太繁琐了。
因此我们换了一种思路:即隐式的插入一个CAST。相当于把 select 1 = '1' 转换成了 select 1 = cast('1' as int),从而在sql编译的前端实现了转换,兼容性上不会有任何问题。
hive视图兼容
presto和hive语义不同,自然hive定义的视图presto不能访问,但对一些简单的视图定义,如:
select a,b,c from tableA
我们可以提供支持,方法也很简单:即在presto读取视图定义(StatementAnalyzer.java)的时候,解析原始的sql定义的语句,转换成presto的视图结构。
总结
- 对于业务开发的一些udf函数的支持;
- 对map结构的解析,比如map数据"{fk_1=1,fk_2:2,fk_3:3}",在hive 1.x 中使用"colelction.delim"作为值之间的分割符;而 hive 3.x 用"collection.delim" ;Prestosql 315则依赖于 hive 3.x,导致对线上的hive 1.x中的map数据解析出现问题。
当然presto对于hive的兼容工作远不止这些,udtf,hive对null处理等等,涉及到方方面面的细节,这也凸显了统一的sql标准的重要性。
本文原文:https://segmentfault.com/a/1190000021236204,来自 OPPO互联网技术团队。
本博客文章除特别声明,全部都是原创!原创文章版权归过往记忆大数据(过往记忆)所有,未经许可不得转载。
本文链接: 【Hive 迁移到 Presto 在 OPPO 的实践】(https://www.iteblog.com/archives/9937.html)