Hive中带条件查询时报Class org.apache.hive.hcatalog.data.JsonSerDe not found的错误及解决办法


    数据计算平台重新搭建成功后,一切顠红,看起来心情就是舒畅,放个截图让心情爽一把:

    

    后续当然需要做一些验证性的工作,以确保安装成功后一切都是执行OK的。

    先放一些测试的JSON文件到HDFS的/tmp/test_json目录下,然后打开HUE界面,进行Hive SQL执行窗口,先创建一个基于JSON文件的外部表:        

CREATE TABLE json_table(`_id` STRING,`key` string, value string)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS TEXTFILE
location '/tmp/test_json';
    然后执行一下查询语句:    

SELECT * from json_table; 
    结果可以正常展示,然后再执行一个带条件的查询语句:    

SELECT * from json_table where `_id`='key1';
    此时就报错了,Hive的日志中体现出来的错误大致如下:    

java.lang.RuntimeException: Map operator initialization failed: org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassNotFoundException: Class org.apache.hive.hcatalog.data.JsonSerDe not found
    根据排查,该类存在于hive的hcategory包中,通过查找,其在我服务器的准确位置为/opt/cloudera/parcels/CDH-5.14.2-1.cdh5.14.2.p0.3/jars/hive-hcatalog-core-1.1.0-cdh5.14.2.jar。

    这个错误虽然是Hive日志中暴露出来的,但是很显然Hive中肯定是已经引入了这个包的,要不然第一条不带条件的语句是不可能执行成功的,这个应该是Hive调用的其它应用报出来的。

    经过分析,Hive在执行不带条件的SQL语句时,如下:    

select * from xx;
select * from xx limit 100;
    HIVE为了加快执行速度,是通过Fetch task模式执行的,而没有使用MR模式,因为这里没有涉及到复杂的计算,纯粹只是为了获取数据,这样处理可以节约处理的时间,也减少将其转换为MR模式的内存和CPU开销。

    MR是通过YARN来最终执行的,而YARN中配置的MR执行引擎是Spark,因而需要在YARN和Spark中增加hive-hcatalog-core-1.1.0-cdh5.14.2.jar的引用,话说虽然简单,但是执行起来还是经过了一些折腾,特别是给Spark增加Jar包的引入。

    以下是给Spark增加lib包的失败尝试:

1.在${CDH_HOME}/lib/spark/lib目录下建立jar包的软链接;
2.把jar包拷贝到${CDH_HOME}/lib/spark/lib目录下;
3.在${CDH_HOME}/lib/spark/conf/classpath.txt中增加jar包路径;
4.在${CDH_HOME}/lib/spark/conf/spark-env.sh中增加jar包路径的路径;
    每次做了以上的修改后,然后在CM上面重启spark,都希望这次修改能够生效,把依赖的Jar包加到Spark的运行环境中,可以每次回到命令行查看spark的classpath都没有将需要依赖的jar加进去,每次都伤心。
    正在无解之时,无意中查看spark的启动参数时,发现spark使用的配置参数路径并不是我修改的spark的配置文件的路径,如下:    
--properties-file /run/cloudera-scm-agent/process/797-spark_on_yarn-SPARK_YARN_HISTORY_SERVER/spark-conf/spark-history-server.conf
    而我修改的spark的配置文件路径是:    
${CDH_HOME}/lib/spark/conf/
    终于知道是CM的原因了,因为CM会在重新生成配置文件,即使${CDH_HOME}/lib/spark/conf/这个路径下面的配置文件也是根据CM中spark的配置生成的,即使在这个目录下做了修改,也会被CM给重写覆盖掉,测试的结果并不是CM每次都会重写这下面的配置文件,并不是每次通过CM重启spark这下面的配置文件都会修改,所以才不那么容易发现问题。

    正确的解决办法:
    1.在Spark中增加新的Jar包

    在CM的spark配置文件所在页面,在“configuration->Filter->Category->Advanced->Spark Service Advanced Configuration Snippet (Safety Valve) for spark-conf/spark-env.sh”配置项中增加以下内容:    

#以下脚本会写入的spark-env.sh中,是把外部目录下面的所有jar全部都加到spark的classpath
#/data/share_libs是共享外部类存放的路径,每台服务器上都有这个目录,hive-hcatalog-core-1.1.0-cdh5.14.2.jar已经在这下目录下建立了软链接到真实的文件

export SHARE_JAR_HOME=/data/share_libs
for f in $SHARE_JAR_HOME/*.jar 
do
SHARE_JAR_CLASSPATH=$f:$SHARE_JAR_CLASSPATH
done
export SHARE_JAR_CLASSPATH
export SPARK_DIST_CLASSPATH=$SHARE_JAR_CLASSPATH$SPARK_DIST_CLASSPATH
    加上以上脚本重启spark后,终于可以在命令行看到spark的classpath中包括了hive-hcatalog-core-1.1.0-cdh5.13.1.jar依赖jar包,spark本身已经不会报错找不到依赖的类了。

    2.给Yarn增加

    找到yarn所在的目录${CDH_HOME}/lib/hadoop-yarn,在里面建立hive-hcatalog-core-1.1.0-cdh5.14.2.jar文件的软链接,每台服务器的yarn目录都建立这个软链接,然后重启yarn服务器,这个再执行终于不会报错了。
————————————————

你可能感兴趣的:(Hadoop,CDH,hive)