HiveSQL语句的正确执⾏顺序
关于 sql 语句的执⾏顺序⽹上有很多资料,但是⼤多都没进⾏验证,并且很多都有点⼩错误,尤其是对于 select 和 group by 执⾏的先后顺序,有说 select 先执⾏,有说 group by 先执⾏,到底它俩谁先执⾏呢?
今天我们通过 explain 来验证下 sql 的执⾏顺序。
在验证之前,先说结论,Hive 中 sql 语句的执⾏顺序如下:
from .. where .. join .. on .. select .. group by .. select .. having .. distinct .. order by .. limit .. union/union all
可以看到 group by 是在两个 select 之间,我们知道 Hive 是默认开启 map 端的 group by 分组的,所以在 map 端是 select 先执⾏,在 reduce 端是 group by 先执⾏。
下⾯我们通过⼀个 sql 语句分析下:
select
der_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;
上⾯这条 sql 语句是可以成功执⾏的,我们看下它在 MR 中的执⾏顺序:
Map 阶段:
1. 执⾏ from,进⾏表的查与加载;
2. 执⾏ where,注意:sql 语句中 left join 写在 where 之前的,但是实际执⾏先执⾏ where 操作,因为 Hive 会对语句进⾏优化,如果符合谓词下推规则,将进⾏谓
词下推;
3. 执⾏ left join 操作,按照 key 进⾏表的关联;
4. 执⾏输出列的操作,注意: select 后⾯只有两个字段(order_amount,userkey),此时 Hive 是否只输出这两个字段呢,当然不是,因为 group by 的是 idno,
如果只输出 select 的两个字段,后⾯ group by 将没有办法对 idno 进⾏分组,所以此时输出的字段有三个:idno,order_amount,userkey;
5. 执⾏ map 端的 group by,此时的分组⽅式采⽤的是哈希分组,按照 idno 分组,进⾏
order_amount 的 sum 操作和 userkey 的 count 操作,最后按照 idno 进⾏排序(group by 默认会附带排序操作);
Reduce 阶段:
6. 执⾏ reduce 端的 group by,此时的分组⽅式采⽤的是合并分组,对 map 端发来的数据按照 idno 进⾏分组合并,同时进⾏聚合操作 sum(order_amount)和
count(userkey);
7. 执⾏ select,此时输出的就只有 select 的两个字段:sum(order_amount) as sum_amount,count(userkey) as count_user;
8. 执⾏ having,此时才开始执⾏ group by 后的 having 操作,对 count_user 进⾏过滤,注意:因为上⼀步输出的只有 select 的两个字段了,所以 having 的过滤字
段只能是这两个字段;
9. 执⾏ limit,限制输出的⾏数为 10。
上⾯这个执⾏顺序到底对不对呢,我们可以通过 explain 执⾏计划来看下,内容过多,我们分阶段来看。
1. ⾸先看下 sql 语句的执⾏依赖:
我们看到 Stage-5 是根,也就是最先执⾏ Stage-5,Stage-2 依赖 Stage-5,Stage-0 依赖 Stage-2。
2. ⾸先执⾏ Stage-5:
图中标①处是表扫描操作,注意先扫描的 b 表,也就是 left join 后⾯的表,然后进⾏过滤操作(图中标②处),我们 sql 语句中是对 a 表进⾏的过滤,但是 Hive 也会⾃动对 b 表进⾏相同的过滤操作,这样可以减少关联的数据量。
3. 接下来执⾏ Stage-2:
⾸先是 Map 端操作:
先扫描 a 表(图中标①处);接下来进⾏过滤操作 idno > '112233'(图中标②处);然后进⾏ left join,关联的 key 是 idno(图中标③处);执⾏完关联操作之后会进⾏输出操作,输出的是三个字段,包括 select 的两个字段加 group by 的⼀个字段(图中标④处);然后进⾏ group by 操作,分组⽅式是 hash(图中标⑤处);然后进⾏排序操作,按照 idno 进⾏正向排序(图中标⑥处)。
然后是 Reduce 端操作:
⾸先进⾏ group by 操作,注意此时的分组⽅式是 mergepartial 合并分组(图中标①处);然后进⾏ select 操作,此时输出的字段只有两个了,输出的⾏数是 30304 ⾏(图中标②处);接下来执⾏ having 的过滤操作,过滤出 count_user>1 的字段,输出的⾏数是 10101 ⾏(图中标③处);然后进⾏ limit 限制输出的⾏数(图中标④处);图中标⑤处表⽰是否对⽂件压缩,false 不压缩。
执⾏计划中的数据量只是预测的数据量,不是真实运⾏的,所以数据可能不准!
4. 最后是 Stage-0 阶段:
限制最终输出的⾏数为 10 ⾏。
总结
通过上⾯对 SQL 执⾏计划的分析,总结以下⼏点:
1. 每个 stage 都是⼀个独⽴的 MR,复杂的 hive sql 语句可以产⽣多个 stage,可以通过执⾏计划的描
述,看看具体步骤是什么。
2. 对于 group by 的 key,必须是表中的字段,对于 having 的 key,必须是 select 的字段。
sql语句优化方式
3. order by 是在 select 后执⾏的,所以 order by 的 key 必须是 select 的字段。
4. select 最好指明字段,select *会增加很多不必要的消耗(CPU、IO、内存、⽹络带宽)。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。