Hive的join方式

    xiaoxiao2025-07-20  9

    Hive的三种join方式:

    Common/Shuffle/Reduce Join(正常/一般情况) Map Join(大小表join、不等值join、结合union all) SMB(Sort-Merge-Buket) Join(大表join大表)

    Shuffle Join

      Shuffle Join在Hive中也叫Common Join或Reduce Join。如果两边数据量都很大,它会进行把相同key的value合在一起,然后再去组合。

    • Map阶段: o 读取源表的数据,Map输出时候以Join on条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key,Map输出的value为join之后所关心的(select或者where中需要用到的)列;同时在value中还会包含表的Tag信息,用于标明此value对应哪个表 • Shuffle阶段: o 根据key的值进行hash,并将key/value按照hash值推送至不同的reduce中,这样确保两个表中相同的key位于同一个reduce中 • Reduce阶段: o 根据key的值完成join操作,期间通过Tag来识别不同表中的数据

    Map Join

      Map Join是在Map阶段进行表之间的连接,而不需要进入到Reduce阶段才进行连接,节省了在Shuffle阶段时要进行的大量数据传输,从而起到了优化作业的作用。Hive内置提供的优化机制之一就包括Map Join。

    Map Join的原理:   其原理是broadcast join,即把小表作为一个完整的驱动表来进行join操作。通常情况下,要连接的各个表里面的数据会分布在不同的Map中进行处理。要使Map Join能够顺利进行,就必须满足:除了一份表的数据分布在不同的Map中外,其他连接的表的数据必须在每个Map中有完整的拷贝。Map Join会把小表全部读入内存中,在Map阶段直接拿另外一个表的数据和内存中表数据做匹配 (这时可以使用DistributedCache将小表分发到各个节点上,以供Mapper加载使用),由于在Map时进行了join操作,省去了Reduce运行的效率也会高很多。

    Map Join的实现方法: 1)在Map-Reduce的驱动程序中使用静态方法DistributedCache.addCacheFile()增加要拷贝的小表文件。 JobTracker在作业启动之前会获取这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。 2)在Map类的setup方法中使用DistributedCache.getLocalCacheFiles()方法获取文件目录,并使用标准的文件读写API读取相应的文件。

    Hive版本区别:   Hive 0.7之前,需要给出Map Join的指示,Hive才会提供Map Join的优化。Hive v0.7之后的版本已经不需要给出MapJoin的指示就进行优化。它是通过如下配置参数来控制的:set hive.auto.convert.join=true;

    Hive 0.11之后,在表的大小符合设置时:

    hive.auto.convert.join.noconditionaltask=true;hive.auto.convert.join.noconditionaltask.size=10000; hive.mapjoin.smalltable.filesize=25000000

    默认会把join转换为map join

    Hive 0.12版本,缺省状况下Map Join优化是打开的,也就是hive.auto.convert.join=true。Hive还提供另外一个参数:表文件的大小作为开启和关闭MapJoin的阈值:hive.mapjoin.smalltable.filesize=25000000

    Map Join适用的场景: 1) 大小表连接   如果一张表的数据很大,另外一张表很少(<1000行),那么可以将数据量少的那张表放到内存里面,在map端做join。Hive支持Map Join,用法如下:

    select / *+ MAPJOIN(time_dim) */ count(1) from store_sales join time_dim on (ss_sold_time_sk = t_time_sk)

    2) 需要做不等值join操作(a.x < b.y或者a.x like b.y等)   这种操作如果直接使用join的话语法不支持不等于操作,Hive语法解析会直接抛出错误。如果把不等于写到where里会造成笛卡尔积,数据异常增大,速度会很慢甚至任务无法跑成功。根据map join的计算原理,map join会把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配。这种情况下即使笛卡尔积也不会对任务运行速度造成太大的效率影响。而且Hive的where条件本身就是在map阶段进行的操作,所以在where里写入不等值比对的话,也不会造成额外负担。

    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;

    3)map join结合UNIONALL   某些情况下join特别慢,可以观察数据,取出特殊(数据特别多的)字段范围放在一组,并使用map join与维表关联,放入内存中,除此之外的数据存入另一组,使用普通join,最后union all放到一起。当设置为true的时候,Hive会自动获取两张表的数据,判定哪个是小表,然后放在内存中。设置:

    set hive.auto.convert.join=true; select count(*) from store_sales join time_dim on (ss_sold_time_sk = t_time_sk) ;

    SMB Join

      大表join大表时,SMB join会自动根据相同的字段进行类似分区分桶的操作,将大表拆成更小一点的表再进行join。设置:

    set hive.auto.convert.sortmerge.join=true (默认是falseset hive.optimize.bucketmapjoin=true; set hive.optimize.bucketmapjoin.sortedmerge=true;
    最新回复(0)