zoukankan      html  css  js  c++  java
  • Hive 的 Join

    1、hive中的join类型:

    (1)join :只返回关联上的结果。

    (2)left join :返回的记录条数和左表相同,关联不上的字段为null。

    (3)right join:返回的记录条数和右表相同,关联不上的字段为null。

    (4)full join:返回两个表的记录去重之和,关联不上的字段为NULL。

    (5)left semi join:左边表为主表,返回主表的KEY也在副表中的记录。

    (6)cross join:返回两表记录的笛卡尔积。

    具体:https://www.cnblogs.com/liupengpengg/p/7908274.html

    2、普通join的原理

    (1) reduce join:也叫common join 或者 shuffle join

      这种join就是两个表的数据量都很大的时候,这时候map执行完毕后,利用 shuffle 将两个表 key 相同的 (key,value) 都放到一个reduce当中,然后进行 join 组合。

      common join的原理是利用map将数据从数据源加载过来,并将on后面的条件当做key,将要查询的字段+tag当做value,其中tag是用来标识value是来自哪一张表。然后通过shuffle,利用key的hash值,将其传输到不同的reduce中。然后在reduce当中按照key进行聚合操作。返回查询结果。

            这其中的弊端就是map端没有预聚合,所有的key,value都要经过网络传输,而所有的聚合操作都在reduce当中,容易发生数据倾斜。

    3、hive中join的优化:

    (1)map join :会将指定表放进内存当中,让所有的map都有小表的拷贝,在map阶段就直接拿另一张表和内存中的表进行join。有一下三种情况使用。

      map join是在小表join大表的场景。先将小表加载到所有节点的内存当中,直接在map阶段,在每个分区中就先进行join,无需在将相同的key shuffle到同一个分区。然后再讲聚合后的结果,shuffle到reduce当中,再进行最终的聚合操作。

           这样做的好处就是使用map端预先join进行预聚合,减少网络传输,减轻reduce压力,解决数据倾斜问题。

    a、大表 join 小表:这时候用map join 将小表(<1000行)放进内存中,在map端进行jion数据匹配操作。

    b、做不等值 join 操作:(a.x<b.y 或 a.x like b.y 等)

      这种操作如果直接使用map的话,hive会报错,若把不能操作写到where当中,可能造成笛卡尔积,数据异常增大,导致运行过慢甚至不成功。

      因此直接用map join直接在map阶段用内存中的表和另一张表进行join操作。

    c、mapjoin结合unionall:遇到时候再研究

    参考博客,原理讲的好:https://www.cnblogs.com/qiuhong10/p/7698277.html 

    (2)SMB(sort-merge-bucket) join:为了解决大表join大表效率慢的问题,使用该join方式 。

    原理:在后台重新创建两张分桶表,同一个桶和对应桶进行join。在分桶的时候,已经对join的key进行了排序,两个表对应的桶内的数据可以直接进行jion。分桶其实就是把大表化成了“小表”,然后 Map-Side Join 解决之,这是典型的分而治之的思想。

     这种join需要是通过设置响应参数来实现:

    set hive.auto.convert.sortmerge.join=true
    
    set hive.optimize.bucketmapjoin=true;
    
    set hive.optimize.bucketmapjoin.sortedmerge=true;

    set hive.auto.convert.sortmerge.join.noconditionaltask=true;  

    set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;

    示例:

    测试:一个4000万和一个5000多万的表Join,关联键数据倾斜,并且笛卡尔积,效果明显。

    建立小表

    create table lxw_test1(id int,name string,date_time string)  
    clustered by(id) sorted by(id) into 10 buckets;  

    建立大表

    create table lxw_test2(id int,name string,date_time string)  
    clustered by(id) sorted by(id) into 5 buckets;  

    启用桶表

    set hive.enforce.bucketing = true;  

    往小表中插入4000万条记录

      insert overwrite table lxw_test1  
      select id,name,null    
      from woa_all_user_info_his   
      where pt = '2012-05-28'  
      limit 40000000;  

    往大表中插5000多万条记录(woa_all_user_info_his中有5000多万条记录)

     insert overwrite table lxw_test2  
     select id,name,date_time  
     from woa_all_user_info_his  
     where pt = '2012-05-28';  

    设置Sort Merge Bucket Map Join的参数

    set hive.optimize.bucketmapjoin = true;  
    set hive.optimize.bucketmapjoin.sortedmerge = true;  
    set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;  

    ps:此时的状况是Bucket columns==Join Columns==Sort Columns,完全具备具备使用Sort Merge Bucket Map Join的条件。

    查询

    select /*+ mapjoin(b) */ count(1)  
    from lxw_test1 a   
    join lxw_test2 b  
    on a.id = b.id   

    测试结果:

    包括insert数据,采用Sort Merge Bucket Map Join的方式耗时10分钟左右。

    如果这两个表做普通的join,耗时1个多小时,还跑不完,最后只得Kill掉了!

    参考博客:http://www.360doc.com/content/19/0828/22/14808334_857638864.shtml

  • 相关阅读:
    CRM
    eclipse 全局替换
    ps 泡泡
    SSH重新登录的问题
    又说oracle spatial 将Geometry转为gml
    其实你可以这样折腾java enum
    Sqlite 多线程入库
    Oracle spatial 将Geometry转换为gml字符串
    Oracle 关于WKT构造SDO_GEOMETRY的问题。
    Lucene之拉框查询
  • 原文地址:https://www.cnblogs.com/guoyu1/p/12123119.html
Copyright © 2011-2022 走看看