上周我们的production环境正式上线了hive 0.11/spark 0.8/shark 0.8,在前期的测试和回归过程中碰到了很多坑,这边记录一下,有其他公司要上的话,可以少走些弯路。
1. Hive 0.11对于每一个分区维护了各自的Schema信息,而0.9中的分区是复用Table Schema来做字段的Serde,如果一张表新增字段,再创建分区,新建的分区会继承Table Schema,而之前的分区如果不drop重建,则会保持新增列之前老的Table Schema,即使底层HDFS文件上补上了新增字段的数据,hive中读出来也是NULL,由于我们dw之前的建表规范是创建表后先预建半年的分区,所以这个问题就被放大了,0.11上对于这个feature的jira是https://issues.apache.org/jira/browse/HIVE-3833,如果要解决这个问题,一种方式是对于所有预建的表都drop重建,然后废弃之前预建的规范,但是这个cost比较大,我们采取了第二种方式,回滚这个feature,分区下数据都用table schema来读,而不用partition schema
我们的shark在branch-0.8基础上merge branch hive0.11的,这个branch由wandisco的人贡献,shark里面会通过反射使用Hive的API,所以需要做API兼容,shark同样需要回滚上面这个feature,否则会抛NoSuchMethodException
4. hive自带UDF round在0.9时返回LongWritable,而0.11中返回DoubleWritable,由于类型不匹配导致cast报错。解决方法是在我们的UDF中增加0.9的round实现来覆盖0.11内置的round实现
5. 用户在hive session内添加自定义Jar包(add jar xx.jar),如果在本地MapRedLocalTask执行用到(比如做ExprNode转换和过滤),会抛ClassNotFoundException,这个应该是Hive的一个bug,我们后续会修掉,目前work-around方式是用户主动在Session中set hive.aux.jars.path=file:///tmp/xxx/xxx.jar,显示加入Local Task的ClassPath中
11. group by语句产生的结果数据有错误,相同group by key会产生多行,比如语句"select x, count(*) from (select x, y from abc group by x,y) a group by x;", 0.11中只会起一个MR Job,ReduceSinkOperator的key是x,y,导致相同x的数据会分布在不同的reduce task中。正确的情况下还会起第二个MR Job,来对x做distribution。0.12已经fix了这个问题(见https://issues.apache.org/jira/browse/HIVE-5237 , https://issues.apache.org/jira/browse/HIVE-5149),另外workaround方式可以关闭优化器set hive.optimize.reducededuplication=false
12. 0.11中默认已经忽略map join hint了(https://issues.apache.org/jira/browse/HIVE-4042),map join都是通过hive.auto.convert.join自动来转换
13. hive run command文件(.hiverc)从$HIVE_HOME/bin下切换到$HIVE_HOME/conf下, "Putting the global hiverc in "$HIVE_HOME/bin/.hiverc is deprecated. Please use $HIVE_CONF_DIR/.hiverc instead."
14. grant赋权语法和之前不同,不支持"dbname.tablename"形式了,比如‘GRANT Select,Show_Database ON TABLE `bi.dprpt_dp_target_shop_mtd_summary` to user `ba_crm_online`;’ 会报错找不到表bi.dprpt_dp_target_shop_mtd_summary,需要先use database再grant tablename,比如'use bi;GRANT Select,Show_Database ON TABLE dprpt_dp_target_shop_mtd_summary to user `ba_crm_online`;'
这次我们是直接从0.9跳过0.10升0.11的,hive社区很活跃,代码改动很频繁,新的feature不断的在加入,并且逐渐开始向SQL92标准靠拢,各方面也都在不断完善中,上面提到有些坑其实是开发编码规范的问题,由于编译阶段预检查更严格,导致之前隐藏比较深的问题暴露出来了,这是好事,通过这些fail-fast的报错,能帮助我们完善Hive的开发规范,包括如何建表,如何写语句,如何设置优化参数等等,使开发人员保持一致的code style,同时降低日后代码的可维护成本。