sparksql 读取hive表子目录问题排查

版本:spark3.0.2

1.1. 问题现象:

    业务使用hive union all产生的数据目录如下,sparksql无法读取该子目录下的数据。select * from table 这种简单的sql也无法读取。

一些博客建议设置下面两个参数,spark.hive.mapred.supports.subdirectories=true和spark.hadoop.mapreduce.input.fileinputformat.input.dir.recursive=true, 设置后sparksql依然无法读取,问题依然存在。

1.2. 问题分析:

      查看物理执行计划,叶子节点为FileSourceScanExec,该执行计划是spark内置的读取文件的SparkPlan,根本就不会使用spark.hive.mapred.supports.subdirectories和spark.hadoop.mapreduce.input.fileinputformat.input.dir.recursive,这两个配置。

      那么在FileSourceScanExec的逻辑中,是否能够处理这种子目录的情况呢。答案是目前FileSourceScanExec无法递归处理子目录:

      FileSourceScanExec的selectedPartitions的属性保存了需要的读取的分区文件,这些文件信息来自PartitioningAwareFileIndex的listFiles方法。leafDirToChildrenFiles这个map中保存的是子目录和数据文件的映射,而path为分区路径,所以这里get返回为空。

         既然FileSourceScanExec无法处理子目录,那有没有其他SparkPlan能够处理呢?

         spark读取hive表时,hive表在logicPlan中其实最开始是HiveTableRelation,然后HiveSessionStateBuilder的postHocResolutionRules中的RelationConversions规则,将HiveTableRelation转换成了LogicalRelation。这个LogicalRelation最终会转换成FileSourceScanExec。

        如果RelationConversions规则不生效,HiveTableRelation就不会转换成LogicalRelation,那最终HiveTableRelation对应的SparkPlan为HiveTableScanExec,在HiveTableScanExec中能够使用spark.hadoop.mapred.input.dir.recursive=true配置读取子目录。

        所以如何控制RelationConversions规则是否生效,见代码。 如果数据文件是orc,那么就设置spark.sql.hive.convertMetastoreOrc=false,如果数据文件是parquet,就设置spark.sql.hive.convertMetastoreParquet=false。 设置了参数后RelationConversions规则就不会生效。

1.3. 问题解决方法

如果是orc文件:
--conf spark.hadoop.mapred.input.dir.recursive=true --conf spark.sql.hive.convertMetastoreOrc=false
如果是parquet文件:
--conf spark.hadoop.mapred.input.dir.recursive=true --conf spark.sql.hive.convertMetastoreParquet=false

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值