join的原理

hive 执行引擎会将Hql的代码翻译为一个一个的map-「shuffle」-reduce 操作,所以实际上join操作都是基于一个或者多个的mr操作。

对于连续的多表join来说,如果多张表join时使用同一列「字段」作为关联了解,那么这些join则会被翻译成一个reduce任务,否则将会被翻译为多个redude任务。

eg1「会被翻译成一个reduce」:

-- 由于使用的join key「关联字段」是同一列,
-- 会被翻译成一个reduce任务
select 
     t1.user_id
    ,t1.user_name
    ,t2.mem_account
    ,t3.order_account
from user t1 
left outer join member t2 
on t1.user_id = t2.mem_id 
left outer join order t3 
on t1.user_id = t3.user_id
;

 

eg2「被翻译为多个reduce」:

-- 由于使用的join key「关联字段」是多个列,
-- 会被翻译成多个reduce任务
select 
     t1.user_id
    ,t1.user_name
    ,t2.mem_account
    ,t3.order_account
from user t1 
left outer join member t2 
on t1.user_id = t2.mem_id 
left outer join order t3 
on t2.mem_credit_id = t3.credit_id
;

join的分类

join 在原理上可分为3大类:

1. common join 

    正常的mapper-shuffle-reduce 过程, 在reduce阶段完成join

2. mapjoin

    顾名思义,在map端直接完成join,在本地操作,减少了shuffle操作「主要是网络传输」。

    可大大提高效率,当join的表都比较大时,有oom的风险

 

3. sort merge bucket join 「SMB」

   smb是sort  merge bucket操作,首先进行排序,继而合并,然后放到所对应的bucket中去。

   bucket是hive中和分区表类似的技术,就是按照key进行hash,相同的hash值都放到相同的buck中去。在进行两个表联合的时候。我们首先进行分桶,在join会大幅度的对性能进行优化。也就是说,在进行联合的时候,是table1中的一小部分和table1中的一小部分进行联合,table联合都是等值连接,相同的key都放到了同一个bucket中去了,那么在联合的时候就会大幅度的减小无关项的扫描。

   原文链接:

 

join的执行过程

1. Map阶段

    读取源表的数据,map输出是以join on 条件中的列作为key , 如果Jon 的条件有多个列,则将这些关联键的组合作为key。

    Map输出的value 为 join之后的集合所需要的列「一般为select 的字段或者是where 条件中需用到的列」,与此同时value中还会包含表的Tag信息,用来标识此value对应的是哪个来源表。

 

2. shuffle 阶段

    根据map阶段的key值进行hash,将key-value的键值对按照hash值推送到不通的reduce中「此操作相当耗时,需要产生较大的网络开销」,这样可确保关联的表中相同的key位于同一个reduce任务中。

 

3. reduce阶段

根据shuffle 后的key值完成 join 操作 ,在此期间通过Tag识别不通来源表的数据。

网友的流程图画的挺好的,我就不再画了,借此一用。

转载链接: 

ps:无任何商业用途,如有冒犯,望及时与我联系。

HIVE in join 效率 hive join 原理_hive

join的优化策略「实战」

1. mapjoin 优化

     基于mapjoin的原理,当大表和小表join时,可使用mapjoin的方式,直接将小表加载到内存中,这样可在map阶段直接完成join操作,极大的提高效率【数倍乃至数十倍的效率提升】

可设置mapjoin的大小、开启mapjoin的转化策略

set hive.mapjoin.smalltable.filesize=300000000; //设置mapjoin小表的文件大小为30M,默认为25M,小表阈值「如果内存够大,也适当调整大一些」

set hive.auto.convert.join=true; //设置自动选择MapJoin,默认是true

2. 数据倾斜优化

    多表join时经常会因为key值的缘故发生数据倾斜「一般是空值倾斜」,数据倾斜后会导致某些reducer处理的数据量过大,导致任务长尾。

  •    当发生空值倾斜时,需要合理利用rand随机函数将空值打散,产生较多的key值,尽可能的将key值分散在各个节点上,最大效率的发挥分布式计算的优势。
select 
     a.user_id
    ,a.user_name
    ,a.text from log a 
left outer join users b 
on case when a.user_id is null then concat('hive',rand() ) 
    else a.user_id 
    end 
= b.user_id;
  • 当发现关联的表中某些少量的key值数据量特别大时,可以将任务拆分为2部分。
-- 非倾斜数据
select 
    A.id f
rom A join B 
on A.id = B.id where A.id <> 1;


-- 倾斜数据
select 
    A.id 
from A join B 
on A.id = B.id 
where A.id = 1 and B.id = 1;

 

3. SMB优化

    原理上文中有,不再多说,直接上代码:

-- 设置相关参数 
set hive.auto.convert.sortmerge.join=true; -- 设置sortmerge
set hive.optimize.bucketmapjoin = true;    -- 设置bucketmapjoin
set hive.optimize.bucketmapjoin.sortedmerge = true;
set hive.auto.convert.sortmerge.join.noconditionaltask=true;


select 
    t1.id
    ,t1.org_level
    ,t2.emp_id
    ,t2.emp_name
from biz_organization  t1 
INNER join biz_emp t2 
on t2.ds = 20190810
and t1.id = t2.org_id;

 

个人看法及感受

        join 作为hql中最常使用的操作,有必要对其原理有一个深刻的了解;需要join基本的优化策略有清楚的认识,并且用于实际的工作中,有的优化策略可能并不常见,但是需要在使用中去慢慢体会,用多了自然就理解。