已复制
全屏展示
复制代码

Hive Join 的实现原理总结


· 3 min read

一. 概要说明

Hive中的Join可分为Reduce Join(Reduce阶段完成join,也叫Common Join)和Map Join(Map阶段完成join)。

二. Hive Reduce Join

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Reduce Join,即在Reduce阶段完成join,整个过程包含Map、Shuffle、Reduce阶段。

2.1 Map阶段

  • 读取源表的数据
  • Map输出时候以Join on条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key;
  • Map输出的value为join之后所关心的(select或者where中需要用到的)列;同时在value中还会包含表的Tag信息,用于标明此value对应哪个表;

2.2 Shuffle阶段

根据key的值进行hash,并将key/value按照hash值推送至不同的reduce中,这样确保两个表中相同的key位于同一个reduce中

2.3 Reduce阶段

根据key的值完成join操作,期间通过Tag来识别不同表中的数据。

SELECT a.id, a.dept, b.age FROM a join b ON a.id = b.id;

三. Hive Map Join

3.1 Join原理

MapJoin通常用于一个很小的表和一个大表进行join的场景,具体小表有多小,由参数 hive.mapjoin.smalltable.filesize 来决定,该参数表示小表的总大小,默认值为25000000字节,即25M。在0.7版本之后,默认自动会转换Map Join,由参数 hive.auto.convert.join 来控制,默认为true,示例如下

Hadoop job information for Stage-3: number of mappers: 1; number of reducers: 0

假设a表为一张大表,b为小表,并且 hive.auto.convert.join=true, 那么Hive在执行时候会自动转化为MapJoin。

  • 首先是Task A,它是一个Local Task,在客户端本地执行的Task,负责扫描小表b的数据,将其转换成一个HashTable的数据结构,并写入本地的文件中,之后将该文件加载到DistributeCache中,该HashTable的数据结构可以抽象为:
key value
1 26
2 34
  • 接下来是Task B,该任务是一个没有Reduce的MR,启动MapTasks扫描大表a,在Map阶段,根据a的每一条记录去和DistributeCache中b表对应的HashTable关联。
  • 把连接结果按key输出,经过shuffle阶段,reduce端得到的就是已经按key分组的,并且连接好了的数据,所以不需要reduce环节了。

3.2 Join场景

  • 当使用 inner join 时,只要其中一个表满足 hive.mapjoin.smalltable.filesize 要求,会自动选择小表作为Hash表。
  • 当使用 left join 时,大表left join小表,加载从右向左,所以小表会加载进内存,存储成Hash键值对。

四. 其他Join事项

4.1 join on条件为null

  • 当为 inner join 时,关联字段为 null 的行会被丢掉
  • 当为 left join 时,右表关联字段为 null 的行会被丢掉,左表关联字段为 null 的行被被保留。
🔗

文章推荐