hive中的mapjoin

今天遇到一个hive的问题,以下hive sql:sql

select f.a,f.b from A t join B f  on ( f.a=t.a and f.ftime=20110802)  app

该语句中B表有30亿行记录,A表只有100行记录,并且B表中数据倾斜特别严重,有一个key上有15亿行记录,在运行过程当中特别的慢,并且在reduece的过程当中遇有内存不够而报错。优化

为了解决用户的这个问题,考虑使用mapjoin,mapjoin的原理:内存

MapJoin简单说就是在Map阶段将小表读入内存,顺序扫描大表完成Join。
上图是Hive MapJoin的原理图,出自Facebook工程师Liyin Tang的一篇介绍Join优化的slice,从图中能够看出MapJoin分为两个阶段:
经过MapReduce Local Task,将小表读入内存,生成HashTableFiles上传至Distributed Cache中,这里会对HashTableFiles进行压缩。
MapReduce Job在Map阶段,每一个Mapper从Distributed Cache读取HashTableFiles到内存中,顺序扫描大表,在Map阶段直接进行Join,将数据传递给下一个MapReduce任务。开发

MAPJION会把小表所有读入内存中,在map阶段直接拿另一个表的数据和内存中表数据作匹配,因为在map是进行了join操做,省去了reduce运行的效率也会高不少test

这样就不会因为数据倾斜致使某个reduce上落数据太多而失败。因而原来的sql能够经过使用hint的方式指定join时使用mapjoin。效率

select /*+ mapjoin(A)*/ f.a,f.b 
from A t join B f  
on ( f.a=t.a and f.ftime=20110802) 

再运行发现执行的效率比之前的写法高了好多。原理

mapjoin还有一个很大的好处是可以进行不等链接的join操做,这种操做若是直接使用join的话语法不支持不等于操做,hive语法解析会直接抛出错误。若是把不等于写到where里会形成笛卡尔积,数据异常增大,速度会很慢。甚至会任务没法跑成功~。select

根据mapjoin的计算原理,MAPJION会把小表所有读入内存中,在map阶段直接拿另一个表的数据和内存中表数据作匹配。这种状况下即便笛卡尔积也不会对任务运行速度形成太大的效率影响。map

并且hive的where条件自己就是在map阶段进行的操做,因此在where里写入不等值比对的话,也不会形成额外负担。

如此看来,使用MAPJOIN开发的程序仅仅使用map一个过程就能够完成不等值join操做,效率还会有很大的提高。

例子:

select /*+ MAPJOIN(a) */ a.start_level, b.* 
from dim_level a join (select * from test) b
 where b.xx>=a.start_level and b.xx<end_level;

简单总结一下,mapjoin的使用场景:

1. 关联操做中有一张表很是小

2.不等值的连接操做

相关文章
相关标签/搜索