Hive从0.11版本开始提供了ORC的文件格式,ORC文件不仅仅是一种列式文件存储格式,最重要的是有着很高的压缩比,并且对于MapReduce 来说是可切分(Split)的。因此,在Hive中使用ORC作为表的文件存储格式,不仅可以很大程度的节省HDFS存储资源,而且对数据的查询和处理性 能有着非常大的提升,因为ORC较其他文件格式压缩比高,查询任务的输入数据量减少,使用的Task也就减少了。
之前有文章介绍过ORC的使用和优化。
更高的压缩比,更好的性能–使用ORC文件格式优化Hive
Hive性能优化之ORC索引–Row Group Index vs Bloom Filter Index
在使用ORC过程中,需要关注Hive中的protobuf版本是否和你使用的Hadoop中protobuf的版本一致,如果不一致,将不能正常使用ORC,比如,我们一个老的Hadoop集群使用的Hadoop版本为hadoop-0.20.2-cdh3u2(protobuf版本为protobuf-java-2.4.0a),Hive的版本为apache-hive-0.13.1-bin(protobuf版本为protobuf-java-2.5.0.jar),这样,在Hive中生成存储格式为ORC的表数据时候便会报错:
FATAL org.apache.hadoop.hive.ql.exec.mr.ExecMapper: java.lang.VerifyError: class org.apache.hadoop.hive.ql.io.orc.OrcProto$RowIndex overrides final method getUnknownFields.()Lcom/google/protobuf/UnknownFieldSet; at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631) at java.lang.ClassLoader.defineClass(ClassLoader.java:615) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141) at java.net.URLClassLoader.defineClass(URLClassLoader.java:283) at java.net.URLClassLoader.access$000(URLClassLoader.java:58) at java.net.URLClassLoader$1.run(URLClassLoader.java:197) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) at org.apache.hadoop.hive.ql.io.orc.WriterImpl.(WriterImpl.java:129) at org.apache.hadoop.hive.ql.io.orc.OrcFile.createWriter(OrcFile.java:369) at org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat$OrcRecordWriter.write(OrcOutputFormat.java:83) at org.apache.hadoop.hive.ql.exec.FileSinkOperator.processOp(FileSinkOperator.java:621) at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:793) at org.apache.hadoop.hive.ql.exec.SelectOperator.processOp(SelectOperator.java:87) at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:793) at org.apache.hadoop.hive.ql.exec.TableScanOperator.processOp(TableScanOperator.java:92) at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:793) at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:540) at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.map(ExecMapper.java:177) at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50) at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:391) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:325) at org.apache.hadoop.mapred.Child$4.run(Child.java:270) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:396) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1127) at org.apache.hadoop.mapred.Child.main(Child.java:264)
很明显,这正是由于Protobuf版本不一致导致的问题。
那么想要解决该问题,如果不是刚开始做版本规划,那么无论是降低Hive版本,还是升级Hadoop版本,都不太容易,上面跑的业务太多了,很容易出现问题。
另一种可行的方法是使用protobuf2.4.0a重新编译Hive0.13.1,这种做法风险最低。
本文介绍如何使用protobuf2.4.0编译Hive0.13.1,使其在较低版本的Hadoop上,可以正常使用ORC文件格式。
下载Hive0.13.1源码:
http://archive.apache.org/dist/hive/
源码解压之后,进入源码根目录,
修改pom.xml
找到<protobuf.version>2.5.0</protobuf.version>,修改为:<protobuf.version>2.4.0a</protobuf.version>
执行编译命令:
mvn clean package -DskipTests -Phadoop-1 -Pdist
其中,参数-Phadoop-1指定了使用MR1的Hadoop。
遇到的第一个错误是在编译hive-exec时候:
[ERROR] symbol: class Parser [ERROR] location: package com.google.protobuf [ERROR] /root/apache-hive-0.13.1-src/ql/src/gen/protobuf/gen-java/org/apache/hadoop/hive/ql/io/orc/OrcProto.java:[12939,31] cannot find symbol [ERROR] symbol: class Parser [ERROR] location: package com.google.protobuf ...... [ERROR] location: package com.google.protobuf [ERROR] /root/apache-hive-0.13.1-src/ql/src/gen/protobuf/gen-java/org/apache/hadoop/hive/ql/io/orc/OrcProto.java:[169,9] getUnknownFields() in org.apache.hadoop.hive.ql.io.orc.OrcProto.IntegerStatistics cannot override getUnknownFields() in com.google.protobuf.GeneratedMessage [ERROR] overridden method is final [ERROR] /root/apache-hive-0.13.1-src/ql/src/gen/protobuf/gen-java/org/apache/hadoop/hive/ql/io/orc/OrcProto.java:[189,20] cannot find symbol [ERROR] symbol: method parseUnknownField(com.google.protobuf.CodedInputStream,com.google.protobuf.UnknownFieldSet.Builder,com.google.protobuf.ExtensionRegistryLite,int) [ERROR] location: class org.apache.hadoop.hive.ql.io.orc.OrcProto.IntegerStatistics [ERROR] /root/apache-hive-0.13.1-src/ql/src/gen/protobuf/gen-java/org/apache/hadoop/hive/ql/io/orc/OrcProto.java:[213,16] cannot find symbol [ERROR] symbol: method setUnfinishedMessage(org.apache.hadoop.hive.ql.io.orc.OrcProto.IntegerStatistics) [ERROR] location: variable e of type com.google.protobuf.InvalidProtocolBufferException [ERROR] /root/apache-hive-0.13.1-src/ql/src/gen/protobuf/gen-java/org/apache/hadoop/hive/ql/io/orc/OrcProto.java:[216,28] cannot find symbol [ERROR] symbol: method setUnfinishedMessage(org.apache.hadoop.hive.ql.io.orc.OrcProto.IntegerStatistics) [ERROR] location: class com.google.protobuf.InvalidProtocolBufferException [ERROR] /root/apache-hive-0.13.1-src/ql/src/gen/protobuf/gen-java/org/apache/hadoop/hive/ql/io/orc/OrcProto.java:[219,9] cannot find symbol [ERROR] symbol: method makeExtensionsImmutable() [ERROR] location: class org.apache.hadoop.hive.ql.io.orc.OrcProto.IntegerStatistics [ERROR] /root/apache-hive-0.13.1-src/ql/src/gen/protobuf/gen-java/org/apache/hadoop/hive/ql/io/orc/OrcProto.java:[230,11] cannot find symbol ......
遇到的第二个错,是编译hive-hbase-hanlder时候:
[ERROR] symbol: class Parser [ERROR] location: package com.google.protobuf [ERROR] /root/apache-hive-0.13.1-src/hcatalog/storage-handlers/hbase/src/gen-java/org/apache/hcatalog/hbase/snapshot/RevisionManagerEndpointProtos.java:[10366,40] cannot find symbol [ERROR] symbol: class Parser [ERROR] location: package com.google.protobuf [ERROR] /root/apache-hive-0.13.1-src/hcatalog/storage-handlers/hbase/src/gen-java/org/apache/hcatalog/hbase/snapshot/RevisionManagerEndpointProtos.java:[10377,33] cannot find symbol [ERROR] symbol: class Parser [ERROR] location: package com.google.protobuf [ERROR] /root/apache-hive-0.13.1-src/hcatalog/storage-handlers/hbase/src/gen-java/org/apache/hcatalog/hbase/snapshot/RevisionManagerEndpointProtos.java:[74,9] getUnknownFields() in org.apache.hcatalog.hbase.snapshot.RevisionManagerEndpointProtos.CreateTableRequest cannot override getUnknownFields() in com.google.protobuf.GeneratedMessage [ERROR] overridden method is final [ERROR] /root/apache-hive-0.13.1-src/hcatalog/storage-handlers/hbase/src/gen-java/org/apache/hcatalog/hbase/snapshot/RevisionManagerEndpointProtos.java:[94,20] cannot find symbol [ERROR] symbol: method parseUnknownField(com.google.protobuf.CodedInputStream,com.google.protobuf.UnknownFieldSet.Builder,com.google.protobuf.ExtensionRegistryLite,int) ......
这两个错误原因相同,涉及到两个类文件:
ql/src/gen/protobuf/gen-java/org/apache/hadoop/hive/ql/io/orc/OrcProto.java
hcatalog/storage-handlers/hbase/src/gen-java/org/apache/hcatalog/hbase/snapshot/RevisionManagerEndpointProtos.java
原因是这两个文件使用protobuf2.5.0生成的,因此不能使用protobuf2.4.0编译。
解决办法是使用protobuf2.4.0,重新生成这两个类文件。
首先需要安装protobuf2.4.0a,下载源码,并解压,进入解压后的根目录,执行下面的命令编译并安装(安装需要root权限):
tar -xzvf protobuf_2.4.0a.orig.tar.gz cd protobuf-2.4.0a/ ./configure make make check make install ##安装完后,查看protoc版本: [root@dev protobuf-2.4.0a]# protoc --version libprotoc 2.4.0
进入Hive-0.13.1源码根目录:
cd /root/apache-hive-0.13.1-src
使用protoc命令重新生成这两个类文件:
protoc ql/src/protobuf/org/apache/hadoop/hive/ql/io/orc/orc_proto.proto --java_out=ql/src/gen/protobuf/gen-java/ protoc ./hcatalog/storage-handlers/hbase/src/protobuf/org/apache/hcatalog/hbase/snapshot/RevisionManagerEndpoint.proto --java_out=hcatalog/storage-handlers/hbase/src/gen-java/
再次执行编译命令:
mvn clean package -DskipTests -Phadoop-1 -Pdist
编译成功,编译之后的hive-exec-0.13.1.jar 位于ql/target目录下,将该jar包拷贝到$HIVE_HOME/lib目录下,覆盖原来的。
重新启动Hive客户端,即可正常生成和查询ORC文件格式的表。
如果需要使用hive-hbase-hanlder,则把hbase-handler/target/hive-hbase-handler-0.13.1.jar复制到$HIVE_HOME/lib下即可。
相关下载:
protobuf_2.4.0a源码:
链接: http://pan.baidu.com/s/1pL2AgIZ 密码: a2hz
基于protobuf-2.4.0a编译好的hive-exec-0.13.1.jar和hive-hbase-handler-0.13.1.jar,如果需要,可以直接下载使用:
链接: http://pan.baidu.com/s/1bpdWgwf 密码: cb43
如果觉得本博客对您有帮助,请 赞助作者 。
转载请注明:lxw的大数据田地 » Hive中使用ORC遇到的protobuf版本问题