Hive中JOIN的使用入门
Hive中join的用法
Hive中Join的通常使用有以下几种:
- inner join 等值连接
- left join
right join
full join - left semi join
- cross join(笛卡尔积)
- mulitiple(一般来说是多个表进行join)
数据准备:
join_a.txt:
1 zhangsan
2 lisi
3 wangwu
join_b.txt:
1 30
2 29
4 21
创建a表并导入数据:
create table a(
id int,name string
)
row format delimited fields terminated by '\t';
hive>load data local inpath '/opt/data/join_a.txt' overwrite into table a;
创建b表并导入数据:
create table b(
id int,age int
)
row format delimited fields terminated by '\t';
hive>load data local inpath '/opt/data/join_b.txt' overwrite into table b;
进行测试
- 普通Join
hive>select a.id,a.name,b.age from a join b on a.id=b.id;
执行结果:
- 左外连接
hive>select a.id,a.name,b.age from a left join b on a.id=b.id;
执行结果:
- 右外连接
hive>select a.id,a.name,b.age from a right join b on a.id=b.id;
执行结果:
因为取的是a.id 所以id为NULL
- 全连接
hive>select a.id,a.name,b.age from a full join b on a.id=b.id;
执行结果:
- 笛卡尔(笛卡尔后面不需要加条件)
hive>select a.id,a.name,b.age from a cross join b;
执行结果:
Common Join和Map Join的MapReduce实现
地址:http://blog.csdn.net/lemonzhaotao/article/details/78209708
由于Hive的底层就是MapReduce,因此通过MapReduce的自己编程,可以进一步了解两者的执行原理,有助于Hive的学习
Common Join实现原理深度剖析
Common Join即传统思路实现Join,性能较差 因为涉及到了shuffle的过程
common join/shuffle join/reduce join (都是指同一个)
执行流程
实现思路(最古老的实现思路)
有a表和b表
以这句SQL为思路: select a.id,a.name,b.age from a join b on a.id=b.id 去实现
通过两个表的id去进行join
1) map 读取 a表 ==> <id, (name)>
<1,(zhangsan)>
<2,(lisi)>
<3,(wangwu)>
2) map 读取 b表 ==> <id, (age)>
<1,(30)>
<2,(29)>
<4,(21)>
3) shuffle: hash(key)
<1,(zhangsan,30)>
<2,(lisi,29)>
<3,(wangwu)>
<4,(21)>
4) reduce
1,(zhangsan,30)
2,(lisi,29)
3,(wangwu)
4,(21)
这种执行流程,会造成的问题
- 数据倾斜
产生该现象的根本原因:某一个key太多,从而导致某一个task的数据量特别大 - shuffle
一旦出现shuffle,性能就会下降很多(不管是在hadoop还是spark中都是一样)
因此在做spark开发的过程中,有一个原则:能避免不使用shuffle就不使用产生shuffle的算子
因为shuffle最耗费性能
MapJoin实现原理深度剖析
mapjoin 也叫作 boardcast join
map join不会有reduce阶段和shuffle阶段
执行流程
- 先启动Task A;Task A去启动一个MapReduce的local task;通过该local task把small table data的数据读取进来;之后会生成一个HashTable Files;之后将该文件加载到分布式 缓存中来;
- 启动MapJoin Task,去读大表的数据,每读一个就会去和Distributed Cache中的数据去关联一次,关联上后进行输出
整个阶段,没有reduce 和 shuffle
原理
- 将小表的数据加载到内存中
- 没有shuffle过程
- 缺点:内存(如果小表过大,可能会出现OOM)
通过执行计划深度剖析Common Join和MapJoin的区别
通过日志打印的信息去对比两种Join操作
非常重要,需要会画两个join的图、知道两者的原理
数据准备
- 数据准备:
dept.txt
10 ACCOUNTINGNEW YORK
20 RESEARCHDALLAS
30 SALESCHICAGO
40 OPERATIONSBOSTON
- 创建dept表
hive>create table dept(deptno int, dname string, loc string) row format delimited fields terminated by '\t';
- 导入数据到dept表
hive>load data local inpath '/opt/data/dept.txt' overwrite into table dept;
测试
hive低版本使用mapjoin必须这样写:
得说明d是小表:/+MAPJOIN(d)/ 告诉hive d是小表
hive>select /*+MAPJOIN(d)*/ e.empno, e.ename, d.dname from emp e join dept d on e.deptno=d.deptno;
注意:在hive中看执行计划是十分重要的一个技能
网址:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Explain
语法:
EXPLAIN [EXTENDED|DEPENDENCY|AUTHORIZATION] query
hive.auto.convert.join参数设置
hive.auto.convert.join=true的意思为:
hive自动会把普通的join转换为mapjoin,也就是哪个表大哪个表小 hive自动会我们进行转换
为了测试看到更好的效果,我们需要将这个值设置为false给参数设置值
hive>set hive.auto.convert.join=false;
- 查看common join执行计划
hive>explain select e.empno, e.ename, d.dname from emp e join dept d on e.deptno=d.deptno;
打印的信息:
打印出信息的部分说明:
TableScan 表示去读表
Filter Operator 表示过滤操作 即 e.deptno=d.deptno
value expressions 表示输出的value字段有哪些
- 查看map join执行计划
hive>set hive.auto.convert.join=true;
hive>explain select e.empno, e.ename, d.dname from emp e join dept d on e.deptno=d.deptno;
打印的执行计划信息:
通过打印在控制台的日志去查看map join:
starting to launch local task
对应 mapreduce local task
Dump ….. hashtable
将hashtable sink出来了(输出出来)
uploaded ….
将hashtable 上传到分布式缓存中了 这个就是小表的流程
End of local task
结束了local task
MapredLocal task successfully
map local task执行成功
Launching Job 1 out of 1
启动一个job
number of mappers:1 number of reducers:0
没有reducer,mapper数量为1
重点:
对于普通join 会生成2个stage
对于mapjoin 会生成3个stage