Hive Join 的原理与机制
Hive 中 的 Join 可分为 Common Join(Reduce阶段完成join)和 Map Join(Map 阶段完成 join)。
Hive Common Join
如果不指定 MapJoin 或者不符合 MapJoin 的条件,那么 Hive 解析器会默认执行 Common Join,即在 Reduce 阶段完成 join。整个过程包含 Map、Shuffle、Reduce 阶段。
Map 阶段
读取源表的数据,Map 输出时候以 Join on 条件中的列为 key,如果 Join 有多个关联键,则以这些关联键的组合作为 key;Map 输出的 value 为 join 之后所关心的( select 或者 where 中需要用到的)列,同时在 value 中还会包含表的 Tag 信息,用于标明此 value 对应哪个表。
Shuffle 阶段
根据 key 的值进行 hash,并将 key/value 按照 hash 值推送至不同的 reduce 中,这样确保两个表中相同的 key 位于同一个 reduce 中。
Reduce 阶段
根据 key 的值完成 join 操作,期间通过 Tag 来识别不同表中的数据。
以下面的HQL为例,图解其过程:
SELECT a.id,a.dept,b.age
FROM a join b
ON (a.id = b.id);
Hive Map Join
MapJoin 通常用于一个很小的表和一个大表进行 join 的场景,具体小表有多小,由参数hive.mapjoin.smalltable.filesize
来决定,默认值为 25M。满足条件的话 Hive 在执行时候会自动转化为 MapJoin,或使用 hint 提示 /*+ mapjoin(table) */
执行 MapJoin。
如上图中的流程,首先 Task A 在客户端本地执行,负责扫描小表 b 的数据,将其转换成一个HashTable 的数据结构,并写入本地的文件中,之后将该文件加载到 DistributeCache 中。
接下来的 Task B 任务是一个没有 Reduce 的 MapReduce,启动 MapTasks 扫描大表 a,在 Map 阶段,根据 a 的每一条记录去和 DistributeCache 中 b 表对应的 HashTable 关联,并直接输出结果,因为没有 Reduce,所以有多少个 Map Task,就有多少个结果文件。
注意:Map JOIN 不适合 FULL/RIGHT OUTER JOIN。
Join 的几种类型
Hive 中 join 有 4 种类型。分别是:
- 内关联(inner join 或者简写成 join)
- 左关联(left outer join 或者简写成 left join)
- 右关联(right outer join 或者简写成 right join)
- 全关联(full outer join 或者简写成 full join)
下面以例子介绍各个 Join 的用法。假如有两个表,一个是客户表(表名:customers),一个是订单表(表名:order)。
客户表数据如下:
ID | Name | Age | Address | Salary |
---|---|---|---|---|
1 | Ross | 32 | Ahmedabad | 2000 |
2 | Rachel | 25 | Delhi | 1500 |
3 | Chandler | 23 | Kota | 2000 |
4 | Monika | 25 | Mumbai | 6500 |
5 | Mike | 27 | Bhopal | 8500 |
6 | Phoebe | 22 | MP | 4500 |
7 | Joey | 24 | Indore | 10000 |
订单表数据如下:
OID | Date | Customer_ID | Amount |
---|---|---|---|
102 | 2016-10-08 00:00:00 | 3 | 3000 |
100 | 2016-10-08 00:00:00 | 3 | 1500 |
101 | 2016-11-20 00:00:00 | 2 | 1560 |
103 | 2015-05-20 00:00:00 | 4 | 2060 |
内关联(inner join、join)
常规 join,类似交集,只显示关联成功的行。如上图所示,它会按照关联条件把左表与右表两者的交集提取出来,作为最终结果。
hive> SELECT c.ID, c.NAME, c.AGE, o.AMOUNT
FROM CUSTOMERS c JOIN ORDERS o
ON (c.ID = o.CUSTOMER_ID);
执行后结果如下:
ID | Name | Age | Amount |
---|---|---|---|
3 | Chandler | 23 | 1300 |
3 | Chandler | 23 | 1500 |
2 | Rachel | 25 | 1560 |
4 | Monika | 25 | 2060 |
左关联(left outer join、left join)
以 left [join] join
关键字前面的表作为主表,和其他表进行关联,返回记录和主表的记录数一致,关联不上的字段会被置为 NULL。 另外是否指定 outer 关键字,对查询结果无影响。
hive> SELECT c.ID, c.NAME, o.AMOUNT, o.DATE
FROM CUSTOMERS c
LEFT OUTER JOIN ORDERS o
ON (c.ID = o.CUSTOMER_ID);
结果如下:
ID | Name | Amount | Date |
---|---|---|---|
1 | Ross | NULL | NULL |
2 | Rachel | 1560 | 2016-11-20 00:00:00 |
3 | Chandler | 3000 | 2016-10-08 00:00:00 |
3 | Chandler | 1500 | 2016-10-08 00:00:00 |
4 | Monika | 2060 | 2015-05-20 00:00:00 |
5 | Mike | NULL | NULL |
6 | Phoebe | NULL | NULL |
7 | Joey | NULL | NULL |
右关联(right outer join、right join)
和左外关联相反,以 right [outer] join 关键词后面的表作为主表,和前面的表做关联,返回记录数和主表一致,关联不上的字段为 NULL。是否指定 outer 关键字,对查询结果无影响。
hive> SELECT c.ID, c.NAME, o.AMOUNT, o.DATE
FROM CUSTOMERS c
RIGHT OUTER JOIN ORDERS o
ON (c.ID = o.CUSTOMER_ID);
结果如下:
ID | Name | Amount | Date |
---|---|---|---|
3 | Chandler | 1300 | 2016-10-08 00:00:00 |
3 | Chandler | 1500 | 2016-10-08 00:00:00 |
2 | Rachel | 1560 | 2016-11-20 00:00:00 |
4 | Monika | 2060 | 2015-05-20 00:00:00 |
全关联(full outer join、full join)
全关联的原理是先左关联再右关联,然后把结果用 union all 合并在一起,关联不到的字段被自动置为 NULL。是否指定 outer 关键字,对查询结果无影响。
hive> SELECT c.ID, c.NAME, o.AMOUNT, o.DATE
FROM CUSTOMERS c
FULL OUTER JOIN ORDERS o
ON (c.ID = o.CUSTOMER_ID);
执行结果如下:
ID | Name | Amount | Date |
---|---|---|---|
1 | Ross | NULL | NULL |
2 | Rachel | 1560 | 2016-11-20 00:00:00 |
3 | Chandler | 3000 | 2016-10-08 00:00:00 |
3 | Chandler | 1500 | 2016-10-08 00:00:00 |
4 | Monika | 2060 | 2015-05-20 00:00:00 |
5 | Mike | NULL | NULL |
6 | Phoebe | NULL | NULL |
7 | Joey | NULL | NULL |
3 | Chandler | 3000 | 2016-10-08 00:00:00 |
3 | Chandler | 1500 | 2016-10-08 00:00:00 |
2 | Rachel | 1560 | 2016-11-20 00:00:00 |
4 | Monika | 2060 | 2015-05-20 00:00:00 |
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论