大象教程
首页
Spark
Hadoop
HDFS
MapReduce
Hive
Hive 教程
Hive 教程
Hive 安装(基于Ubuntu系统)
Hive 架构
Hive 内置函数
Hive UDF 简介
Hive DDL 命令
Hive 视图
Hive 索引
Hive Metastore 的三种配置方式
Hive 数据模型
Hive 数据类型
Hive 操作符
Hive SerDe(序列化与反序列化)
Hive 数据分区
Hive 分桶
Hive 分区与分桶的比较
Hive Join 的原理与机制
Hive map Join
Hive bucket map join
#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为例,图解其过程: ```sql SELECT a.id,a.dept,b.age FROM a join b ON (a.id = b.id); ``` ![hive join 原理](/media/editor/file_1574347200000_20191121224000912759.png "hive join 原理") ##Hive Map Join MapJoin 通常用于一个很小的表和一个大表进行 join 的场景,具体小表有多小,由参数`hive.mapjoin.smalltable.filesize` 来决定,默认值为 25M。满足条件的话 Hive 在执行时候会自动转化为 MapJoin,或使用 hint 提示 `/*+ mapjoin(table) */` 执行 MapJoin。 ![hive map join 原理](/media/editor/file_1574347278000_20191121224119851002.png "hive map join 原理") 如上图中的流程,首先 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 种类型。分别是: 1. 内关联(inner join 或者简写成 join) 2. 左关联(left outer join 或者简写成 left join) 3. 右关联(right outer join 或者简写成 right join) 4. 全关联(full outer join 或者简写成 full join) ![hive join 的几种类型](/media/editor/file_1574347348000_20191121224229399145.png "hive 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,类似交集,只显示关联成功的行。如上图所示,它会按照关联条件把左表与右表两者的交集提取出来,作为最终结果。 ```sql 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 关键字,对查询结果无影响。 ```sql 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 关键字,对查询结果无影响。 ```sql 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 关键字,对查询结果无影响。 ```sql 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|
加我微信交流吧