一、hiveSQL执行顺序
from … where … mapjoin … on … select(筛选有用字段) … group by ||… join … on … select(筛选输出字段) … having … distinct … order by … limit … union/union all
|| 前是map阶段执行,后的reduce阶段执行
以如下hql为例:
select
sum(b.order_amount) sum_amount,
count(a.userkey) count_user
from user_info a
left join user_order b on a.idno=b.idno
where a.idno > '112233'
group by a.idno
having count_user > 1
limit 10;
hql执行顺序如下:
Map 阶段:
1、执行 from,进行表的查找与加载,注意要join的表也要加载进来(MapJoin除外);
2、执行 where,注意: sql 语句中 left join 写在 where 之前的,但是实际执行先执行 where 操作,因为 Hive 会对语句进行优化,如果符合谓词下推规则,将进行谓词下推;
3、如果join的是小表,可以执行 Map join 操作,按照 key 进行表的关联;
4、执行输出列的操作,注意: select 后面只有两个字段(order_amount,userkey),此时 Hive 是否只输出这两个字段呢,当然不是,因为 group by 的是 idno,如果只输出 select 的两个字段,后面 group by 将没有办法对 idno 进行分组,所以此时输出的字段有三个:idno,order_amount,userkey,所以这个select的作用是筛选出需要用到的字段,所以我们在写hql时最好不要用select *;
5、执行 map 端的 group by,此时的分组方式采用的是哈希分组,按照 idno 分组,进行 order_amount 的 sum 操作和 userkey 的 count 操作,最后按照 idno 进行排序(group by 默认会附带排序操作);
Reduce 阶段:
1、执行 reduce 端的 group by,此时的分组方式采用的是合并分组,对 map 端发来的数据按照 idno 进行分组合并,同时进行聚合操作 sum(order_amount)和 count(userkey);
2、执行 select,此时输出的就只有 select 的两个字段:sum(order_amount) as sum_amount,count(userkey) as count_user;
3、执行 having,此时才开始执行 group by 后的 having 操作,对 count_user 进行过滤,注意:因为上一步输出的只有 select 的两个字段了,所以 having 的过滤字段只能是这两个字段;
4、执行 limit,限制输出的行数为 10。
二、HiveSql数据转化过程
以下面sql为例:
hive> SELECT * FROM logs;
OK
a 苹果 5
a 橙子 3
b 烧鸡 1
hive> SELECT * FROM users;
OK
a 23
b 21
hive> SELECT a.uid,a.name,b.age FROM logs a JOIN users b ON (a.uid=b.uid);
a 苹果 23
a 橙子 23
b 烧鸡 21
计算过程:
Map阶段只是拆分key和value。
key这里后面的数字是tag,后面在reduce阶段用来区分来自于那个表的数据。tag是附属在key后面的。那为什么会把a(0)和a(1)汇集在一起了呢,是因为对先对a求了hashc