记录Hive升级0.10遇到的多表full out join等问题和解决

记录下最近Hive升级0.10遇到的一些问题:

由于Hadoop集群升级了Yarn即hadoop-2.0.0-cdh4.3.0,之前的hive 0.8.1版本已经不能使用了。于是将Hive升级到hive-0.10.0-cdh4.3.0版,期间遇到了一些问题,记录在此。

1. 多表(32张表)的full out join任务被拆分成了很多个子任务

这样每个子任务串行,导致整个任务的执行时间很长。主要的原因是在处理outer join时,hive里面用的short变量来保存的别名”aliases”,观察到的现象是5张以上的表做full out join会拆成多个任务完成。hive邮件组上有过三次讨论:123

The problem is mixture of issues (HIVE-3411, HIVE-4209, HIVE-4212,
HIVE-3464) and still not completely fixed even in trunk.

最终采取的方案是,参考邮件组中提到的patch,将用到short的地方改为long。估计官方也会修复这个问题的。

2. 发现 mapreduce.map.tasks 设置的map个数无效
升级后发现mapreduce.map.tasks这个参数无效,无法用来控制map个数。原因是 hive.input.format 的值默认设为org.apache.hadoop.hive.ql.io.CombineHiveInputFormat,这时候,可以只能通过设置mapreduce.input.fileinputformat.split.maxsize=文件大小/期望map个数 来控制map个数。

另一种方法是使用 org.apache.hadoop.hive.ql.io.HiveInputFormat,这样设置mapreduce.map.tasks就能生效。

按官方文档的说法:在hadoop 17,18,19版本之前HiveInputFormat是作为默认的inputformat,在hadoop 20之后,默认的inputformat变为了CombineHiveInputFormat。如果发现bug,用户可以手工将inputformat从CombineHiveInputFormat换回HiveInputFormat。

The default input format, if it is not specified, the system assigns it. It is set to HiveInputFormat for hadoop versions 17, 18 and 19, whereas it is set to CombineHiveInputFormat for hadoop 20. The user can always overwrite it – if there is a bug in Combi neHiveInputFormat, it can always be manually set to HiveInputFormat.

CombineHiveInputFormat的作用是:

(1)把输入目录下的大文件分成多个map的输入

(2)在读取大量小文件时,会在map阶段合并文件,使得一个map可以处理多个部分的文件,保证最小的map代价处理更多的碎文件。

(具体的文件拆分和合并策略可以参考这篇文章:hadoop各种输入方法(InputFormat)汇总)

HiveInputFormat则会对每一个文件启动一个map处理,不合并输入数据。这样如果小文件数量很多,频繁启动map消耗较大。

至于选择CombineHiveInputFormat还是HiveInputFormat,需要根据文件数据量大小,小文件个数,mapred.max.split.size,网络带宽和单map执行时间等来决定。

3. 某个写redis的hive job拆成了两个job
这个job是select一张表的数据插入另外一张表,特殊的地方在于重写了outputformat,数据在写入另外一张表的同时也写了一份到redis。但是job被拆成了两个任务,第二个任务只有1个map。

原因在于:

  • hive中hive.merge.mapfiles 默认为true,表示如果map输出文件太小,会新起一个job合并小文件,以减轻对hdfs的压力。

此外:

  • 参数 hive.merge.mapredfiles 默认为false,表示是否合并 Reduce 输出文件。
  • 合并文件的大小由参数 hive.merge.size.per.task 决定。
  • hive.merge.smallfiles.avgsize 表示当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge

因此,对只有map的hive job,如果不想job被拆分成多个,需要设置:hive.merge.mapfiles=false;

发表评论

电子邮件地址不会被公开。 必填项已用*标注