Hive on tez的insert union 子目录的问题【使用tez,mr无法查询到数据】

Hive on tez的insert union 子目录的问题【使用tez,mr无法查询到数据】

Hive on tez的insert union 子目录的问题【使用tez插入,mr疫情无法查询到数据】

hive tez insert union all问题

问题描述

在hive中使用tez模式时,发现tez的输出结果在对应表目录中,生成了子目录,造成未配置tez的hive客户端对该表进行读取时,无法获取到数据。
检查表的输出目录,在分区目录下发现了两个子目录:1和2:
/user/hive/test1/20170920000000/1
/user/hive/test1/20170920000000/2

原因

查看对应的sql,发现存在insert union操作,查看往上信息,发现tez对于insert union操作会进行优化,通过并行加快速度,为防止有相同文件输出,所以对并行的输出各自生成成了一个子目录,在子目录中存放结果。如果此时全部hive客户端引擎及相关都设定为tez,则无问题。如果有客户端还在使用mr引擎,则会出现读取不到数据的情况。而在hive中,对于表目录存放信息有如下策略:

在Hive默认设置中,hive只能读取对应表目录下的文件,
1)如果表目录中同时存在目录和文件
则使用hive进行读取时,会报目录非文件的错误
2)表目录中只有目录
hive不会进行深层递归查询,只会读取到对应查询目录,会查询结果为空
3)表目录中只有文件
则可以正常查询

Hive on tez 中对insert union操作进行了优化,会并行输出到对应的表目录,为防止有相同名文件存在,所以为各自输出在表目录下各自设置了一个目录,里边存放执行结果
此种目录,对tez引擎客户端可读。但是对于mr引擎,因为其只会便遍历到对应分区层。发现分区下没有文件后,就返回空

解决思路

发现该现象后,从网上搜索解决方案,http://grokbase.com/t/hive/user/162r80a2g9/anyway-to-avoid-creating-subdirectories-by-insert-with-union
经该文章提示,可以开启mapreduce的递归查询模式:
set mapreduce.input.fileinputformat.input.dir.recursive=true
在hive中,设置执行查询后,会提示错误,要求将set hive.mapred.supports.subdirectories=true;
经过两个set后,仔执行查询,hive即可对tez引擎产union产出的数据进行访问。

同时为了查看tez的此种情况对其他引擎的兼容性,又对sparktThriftServer的sql访问进行了测试:

对于sparkthriftserver,只需添加set mapreduce.input.fileinputformat.input.dir.recursive=true ,即可访问对应数据

总结一下sparkThriftServer模式与hive的不同

1)在表目录下同时有文件和目录时(非分区目录)

此时sparkThriftServer和hive都会报非文件错误

2)在表目录下均为目录(非分区目录)

此时sparkThriftServer会报非文件错误,hive无错,但是查询为空

解决方案

方案一:所有hive端都替换为tez引擎

这不会出现上述问题,但会存在对其他引擎如spqrk,mr,presto等的影响

方案二:为hadoop和hive设置可递归读

该方案相对可行,但需要调研对普通mr任务的影响

解决方案来自:https://blog.csdn.net/myg821561935/article/details/78071014