Spark2.3.0远程查询Hive表失败,提示找不到表或视图
Spark 2.3.0 远程Hive表查询失败问题排查与解决
咱们来好好分析下你遇到的Spark 2.3.0远程Hive表查询问题:在Spark 1.6.0中用HiveContext能正常远程查询HDFS集群上的Hive表,但切换到2.3.0后执行相同逻辑就抛出了表不存在的异常,你怀疑程序在本地而非远程查找数据库——这个推测非常合理,下面咱们一步步拆解问题。
你遇到的异常信息
org.apache.spark.sql.AnalysisException: Table or view not found: `hiveorc_replica`.`appointment`; line 1 pos 21; 'Aggregate [unresolvedalias(count(1), None)] +- 'UnresolvedRelation `hiveorc_replica`.`appointment`
当前使用的Spark上下文代码
val conf = new SparkConf().setAppName("SparkApp").setMaster("local") val sc=new SparkContext(conf) val hc = new HiveContext(sc) val actualRecordCountHC = hc.sql("select count(*) from hiveorc_replica.appointment") val records = hc.sql("select * from hiveorc_replica.appointment")
你的hive-site.xml配置片段
<?xml version="1.0" encoding="UTF-8"?> <!--Autogenerated by Cloudera Manager--> <configuration> <property> <name>hive.metastore.uris</name> <value>thrift://fqdn:9083</value> </property> <property> <name>hive.metastore.client.socket.timeout</name> <value>300</value> </property> <property> <name>hive.metastore.warehouse.dir</name> <value>/user/hive/warehouse</value> </property> <property> <name>hive.warehouse.subdir.inherit.perms</name> <value>true</value> </property> <property> <name>hive.auto.convert.join</name> <value>true</value> </property> <property> <name>hive.auto.convert.join.noconditionaltask.size</name> <value>20971520</value> </property> <property> <name>hive.optimize.bucketmapjoin.sortedmerge</name> <value>false</value> </property> <property> <name>hive.smbjoin.cache.rows</name> <value>10000</value> </property> <property> <name>hive.server2.logging.operation.enabled</name> <value>true</value> </property> <property> <name>hive.server2.logging.operation.log.location</name> <value>/var/log/hive/operation_logs</value> </property> <property> <name>mapred.reduce.tasks</name> <value>-1</value> </property> <property> <name>hive.exec.reducers.bytes.per.reducer</name> <value>67108864</value> </property> <property> <name>hive.exec.copyfile.maxsize</name> <value>33554432</value> </property> <property> <name>hive.exec.reducers.max</name> <value>1099</value> </property> <property> <name>hive.vectorized.groupby.checkinterval</name> <value>4096</value> </property> <property> <name>hive.vectorized.groupby.flush.percent</name> <value>0.1</value> </property> <property> <name>hive.compute.query.using.stats</name> <value>false</value> </property> <property> <name>hive.vectorized.execution.enabled</name> <value>false</value> </property> <property> <name>hive.vectorized.execution.reduce.enabled</name> <value>false</value> </property> <property> <name>hive.merge.mapfiles</name> <value>true</value> </property> <property> <name>hive.merge.mapredfiles</name> <value>false</value> </property> <property> <name>hive.cbo.enable</name> <value>false</value> </property> <property> <name>hive.fetch.task.conversion</name> <value>minimal</value> </property> <property> <name>hive.fetch.task.conversion.threshold</name> <value>268435456</value> </property> <property> <name>hive.limit.pushdown.memory.usage</name> <value>0.1</value> </property> <property> <name>hive.merge.sparkfiles</name> <value>true</value> </property> <property> <name>hive.merge.smallfiles.avgsize</name> <value>16777216</value> </property> <property> <name>hive.merge.size.per.task</name> <value>268435456</value> </property> <property> <name>hive.optimize.reducededuplication</name> <value>true</value> </property> <property> <name>hive.optimize.reducededuplication.min.reducer</name> <value>4</value> </property> <property> <name>hive.map.aggr</name>
问题根源
Spark 2.x版本对Hive集成做了重大调整:HiveContext被标记为过时,官方推荐使用SparkSession作为统一的入口;同时,Spark 2.x初始化Hive上下文的逻辑和1.6.x不同,如果还是沿用旧的HiveContext方式,很可能没有正确加载远程Hive元数据配置,导致Spark默认使用本地嵌入式元数据库(比如Derby),自然找不到远程集群上的表。
解决步骤
1. 替换为SparkSession(最推荐)
Spark 2.x中必须用SparkSession来构建支持Hive的上下文,它会自动读取classpath中的hive-site.xml配置,正确连接远程Metastore。修改你的代码如下:
import org.apache.spark.sql.SparkSession val spark = SparkSession.builder() .appName("SparkApp") .master("local") .enableHiveSupport() // 这一步必须加,启用Hive支持 .getOrCreate() // 之后用spark对象执行SQL即可 val actualRecordCountHC = spark.sql("select count(*) from hiveorc_replica.appointment") val records = spark.sql("select * from hiveorc_replica.appointment")
2. 确保hive-site.xml被正确加载
- 确认
hive-site.xml确实放在项目的resources目录下,打包或本地运行时能被Spark的classpath识别到。 - 如果本地运行时还是有问题,可以直接在SparkConf中手动指定Metastore地址,强制Spark连接远程服务:
val conf = new SparkConf() .setAppName("SparkApp") .setMaster("local") .set("hive.metastore.uris", "thrift://fqdn:9083") // 直接指定远程Metastore地址 val sc = new SparkContext(conf) val hc = new HiveContext(sc)
3. 检查依赖是否正确
确保你的项目依赖中包含了Spark Hive的相关jar包,以Maven为例,Spark 2.3.0的依赖应该是:
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-hive_2.11</artifactId> <version>2.3.0</version> </dependency>
如果是sbt项目,对应依赖为:
libraryDependencies += "org.apache.spark" %% "spark-hive" % "2.3.0"
4. 验证元数据连接是否正常
在执行查询前,先运行spark.sql("show databases")(或hc.sql("show databases")),如果能列出远程Hive的hiveorc_replica数据库,说明Metastore连接正常;如果看不到,那就要检查:
hive.metastore.uris中的地址和端口是否正确- 本地机器和远程Metastore服务之间的网络是否通畅(可以用
telnet fqdn 9083测试) - 远程Metastore服务是否正常运行
内容的提问来源于stack exchange,提问作者udit
相关产品推荐
相关产品推荐

