这两天有个hive的任务跑的特别慢,看日志是reduce阶段卡在了99%,虽然任务成功了,但是总耗时4个小时。。。这肯定是无法忍受的。下面记录一下调优的过程。
工作中的代码涉敏,这边用简单的示例SQL。
select coalesce(a.id,b.id), age,name,course, grade
from
(
select id, age, name
from table1
) a
full outer join
(
select id, course, grade
from table2
) b
on a.id = b.id
我的排查思路是这样的:
1、 查看日志中执行耗时很长的那个job,看到相关的url,点击到Hadoop的application页面。
2、查看reduce阶段的耗时情况,判断有可能是什么原因导致的数据倾斜。
查看一:(reduce各个task执行耗时情况)
发现有一个task执行了4个小时。。。 而其他的task只用了一分钟不到
查看二:(通过任务的Counter数判断)
可以在job的主页面里或者上图中reduce task页面,左上角有个 Counter 这一栏。点击去可以看到这个reduce阶段读取或者写入了多少。比如我们就看第一个000000的task,点击进去,左侧有个counter,进去后找到Reduce input groups。如下图:
发现input的数量为788544,而其他task的input数量为424242,还是多了不少,但不会太离谱。
这个时候看了yarn日志里的这两项,我们有理由去怀疑一下是不是由于是大key导致的数据倾斜。
于是去count了一下这两个表id对应的条数。
表1: 表2:
id 总记录数 id 总记录数
1 114514 1 9096
2 92628 2 1346
3 53320 3 1162
4 37851 4 1072
5 24614 5 916
6 20491 6 858
7 17143 7 741
8 16399 8 741
9 16089 9 645
10 15748 10 620
发现记录数差别不会很大,但是!!!两个表都有join的key为空的情况,显然,问题就出现在这!
于是去掉了id不为空的key,任务就没有出现数据倾斜的情况了。
虽然后面问题不是因为大key的原因,偶然性发现是因为key为空的原因,但是原因排查的思路还是没啥问题的。
ps:如果排查后确实是因为大key导致的
1. 可以将大key和其他key分开处理,用where条件过滤该key,再union all其他的key,这样效率会更高一些。
2. 调整reduce的内存大小:
set mapreduce.reduce.memory.mb=4000;
set mapreduce.reduce.java.opts=-Xmx4000m;