文章目录

  • 一、问题现象
  • 二、分析思路
  • 三、排查验证
  • 1、排查范围
  • 2、验证数据质量问题
  • 3、猜想验证
  • 四、得出结论
  • 五、未完待续


一、问题现象

1、多表关联,其中主表与从表1为:inner join 关系;
2、该 SQL 语句在 MySQL 上能正常执行;
3、在Hive上执行时,则会出现GC overhead limit exceeded 导致无法正常执行;

SELECT
       字段1
      ,字段2
      ...
      ,字段N
FROM 		    -- 511298
INNER JOIN		-- 1296078
ON          
LEFT JOIN       -- 1726276
ON                  
LEFT JOIN       -- 375899
on          
LEFT JOIN       -- 332
on          
LEFT JOIN       -- 495000
on          
LEFT JOIN       -- 38
on          
LEFT JOIN       -- 5693
on               
;

以上数字代表:笔者此次所涉及的每张表count(1)后得出的行数。

二、分析思路

  • 该类问题常见猜测:
  •  1、Hive环境是否有问题?
  •  2、相关的表配置是否有问题?
  •  3、是否出现了笛卡尔积?导致数据膨胀。
  •  4、是否出现了数据倾斜?


解决思路:猜测、分段排除;

三、排查验证

1、排查范围

是否是Hive环境?是否是表配置问题?

验证是否所有表都是这样?如果所有表,大概率是Hive执行环境问题,如果只是该SQL语句,则大概率是该SQL语句相关表问题。

该问题,发生时,其他表的SQL执行正常。所以初步定位为该SQL语句中相关表的问题。通过依次实验主表与后面从表JOIN,两两组合。

或者通过执行日志,能够看到在进行到哪张表读取的时候,就失败了。

2、验证数据质量问题

导致两个表Join时,MapReduce慢或者异常。较多的情况是,数据倾斜与笛卡尔集合。

select id,count(*) as cnt
from table
group by id 
order by cnt;

select id,count(*) as cnt 
from table
where id is null and cnt > 1;

使用以上语句,检查发现,id没有为null的,也没有重复的。所以基本排除数据倾斜与笛卡尔集合出现的可能。

3、猜想验证

是否是Inner join使用不对呢,用Left Join试试

SELECT
       字段1
      ,字段2
      ...
      ,字段N
FROM 		    -- 511298
left JOIN		-- 1296078
ON

1、发现:使用 left join 后:就正常啦!这到底是怎么了啊啊(:
2、只能分别对 inner join 和 left join两种情况都查看执行计划咯。
3、explain 安排上了~~
4、最后的最后:仔细对比,多了:

Map Local Tables:;Local Work: | | Map Reduce Local Work
-- 看着像是 mapjoin 优化的东西...
set hive.auto.convert.join;
+------------------------------+--+
|             set              |
+------------------------------+--+
| hive.auto.convert.join=true  |
+------------------------------+--+

难道是优化之后,小表的数据量被分发到各个task的内存中,导致yarn task执行时,内存不足,从而导致前面的报错:GC overhead limit exceeded?

set hive.auto.convert.join=false;
SELECT
       字段1
      ,字段2
      ...
      ,字段N
FROM 		    -- 511298
INNER JOIN		-- 1296078
ON          
LEFT JOIN       -- 1726276
ON                  
LEFT JOIN       -- 375899
on          
LEFT JOIN       -- 332
on          
LEFT JOIN       -- 495000
on          
LEFT JOIN       -- 38
on          
LEFT JOIN       -- 5693
on               
;

四、得出结论

正常执行了。那就确定是hive.auto.convert.join=true默认优化导致的。但是为啥呢?小表数据量太大了?Task的内存配置太小了?小表的数据量统计不准确?LEFT JOIN没有问题呢,Hive有BUG?

五、未完待续

为什么我在没有手动关闭 MapJoin 的情况下:我将 inner join 换成 left join 后,就可以正常执行嘞?为什么 inner join 就需要手动关闭 MapJoin呢??跪求大佬前来递解药:)