Spark2.4.4读取Hive2.3.3 UNION ALL生成ORC表无数据问题咨询
问题1:为什么Spark无法识别表1的数据?
Spark 2.4.4默认读取非分区Hive表时,仅扫描表存储根目录下的直接数据文件,不会递归遍历子目录。你提供的目录结构里,表1的所有ORC数据文件都存放在1/、2/等子目录下,根目录没有任何数据文件,Spark扫描时判定表为空,因此返回0行数据且无报错。
而Hive Beeline默认开启了目录递归扫描配置,因此可以正常读取嵌套子目录下的文件,返回全量数据。
问题2:为什么Hive为表1生成了结构复杂的5个文件,为表2仅生成结构简单的4个文件?
你指定了Hive执行引擎为MR,CTAS(Create Table As Select)语句的任务输出结构和查询的stage数量直接相关:
- 表1的查询包含
UNION ALL,会拆分为两个独立的子查询任务执行,每个子任务的输出默认会写入独立的子目录:第一个子查询(explode逻辑)的输出存到1/目录下,第二个子查询(null值处理逻辑)的输出存到2/目录下,子查询内部如果有多级stage还会额外嵌套子目录,就形成了你看到的多层嵌套结构。 - 表2的查询仅用单条SELECT加
outer explode实现逻辑,没有多任务合并的步骤,因此所有输出文件直接写入表的根目录,没有嵌套子目录,文件数量就是当前查询的并行度对应的输出数。
问题3:存储结构差异是否会影响Spark的读取过程?
会,就是这个存储结构差异直接导致表1读取失败。
Spark对非分区表的默认读取逻辑仅识别根目录下的直接文件,嵌套子目录下的文件默认不会被扫描到。如果需要兼容这种目录结构,可以在Spark任务启动时添加配置:
spark.sql.files.recursiveFileLookup=true
或者读取时直接指定通配符路径扫描子目录:
Dataset<Row> df = sparkSession.read().orc("/user/hive/warehouse/test.db/table1/*/*");
也可以在建表时添加Hive参数避免生成嵌套目录:
set hive.merge.job.results=true; create table test.table1 stored as orc as -- 你的查询逻辑
该参数会将多个任务的输出合并后写入表根目录,不会生成嵌套子目录。
内容的提问来源于stack exchange,提问作者Uroboros
相关产品推荐
相关产品推荐

