Spark读取Hive外部分区表遇文件缺失报错,参数无效求解决
我来帮你拆解问题原因并给出针对性的解决方案:
为什么你设置的参数没生效?
你用到的spark.sql.files.ignoreMissingFiles和spark.sql.files.ignoreCorruptFiles是Spark原生文件数据源(比如直接用spark.read读取Parquet/CSV文件)的专属配置。但当你通过Hive元数据读取外部分区表时,Spark会切换为Hive的InputFormat处理文件读取逻辑,这两个Spark原生参数就不再起作用了。
另外,spark.sql.hive.verifyPartitionPath=false主要是控制Spark插入静态分区时是否验证路径存在,对查询阶段跳过缺失文件的帮助有限。
而Hive能正常返回结果,是因为你的Hive集群默认(或已配置)开启了忽略缺失/损坏文件的参数,它会自动跳过不存在的文件。
正确的解决方案
针对Spark 2.2.0.cloudera1版本,你需要通过Hadoop配置传递Hive的相关参数,让Hive的InputFormat跳过缺失文件,具体操作如下:
1. 在创建SparkSession时添加Hive相关配置
修改你的SparkSession构建代码,加上Hive的忽略参数(注意用spark.hadoop.前缀将参数传递给Hadoop Configuration):
SparkSession.builder .config("spark.sql.hive.verifyPartitionPath", "false") .config("spark.hadoop.hive.ignore.corrupt.files", "true") .config("spark.hadoop.hive.ignore.missing.files", "true") .enableHiveSupport() .getOrCreate()
2. (可选)会话级别直接设置Hive参数
如果上面的配置依然不生效,可以在执行查询前,直接通过Spark SQL执行Hive的SET命令,设置会话级别的参数:
// 先设置Hive参数 spark.sql("SET hive.ignore.corrupt.files=true") spark.sql("SET hive.ignore.missing.files=true") // 再执行计数查询 val sql = "SELECT count(*) FROM db.table WHERE date=20190710" val df = spark.sql(sql) println(df.count)
原理说明
hive.ignore.corrupt.files和hive.ignore.missing.files是Hive的核心参数,开启后Hive的InputFormat会自动跳过损坏或不存在的文件。Spark开启HiveSupport后,会复用Hive的InputFormat读取表数据,所以传递这些参数就能让Spark和Hive的表现保持一致。
这样配置后,你的Spark任务就会像Hive一样忽略缺失文件,正常返回计数结果了。
内容的提问来源于stack exchange,提问作者Gopal Tiwari

