Apache Hive 中 order by、sort by、distribute by、cluster by的区别是什么?

2,613 阅读2分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

正文

  1. order by 会对所给的全部数据进行全局排序,不管来多少数据,都只启动一个reducer来处理 。
  2. sort by 是 局部排序,sort by会根据数据量的大小启动一到多个 reducer 来干活,并且,它会在进入 reduce 之前为每个 reducer 都产生一个排序文件 。
  3. distribute by 控制 map 结果的分发,它会将具有相同字段的 map 输出分发到一个 reduce 节点上做处理 。
  4. cluster by 可以理解为一个特殊的 distribute by 和 sort by 的结合,当 distribute by 和 sort by 后面所跟的列名相同时,就等同于直接使用 cluster by 跟上该列名。但是被cluster by指定的列最终的排序结果只能是降序,而且无法指定 asc 和 desc。

补充

1. order by 全局排序

全局排序,只有一个reduce

使用 order by 子句排序

  1. asc (ascend)—— 升序 (默认)
  2. desc (descend)—— 降序

order by 子句在 select 语句的结尾

2. distribute by 分区排序

distribute by 类似 MapReduce 中 partition,==采集 hash 算法,在 map 端将查询的结果中 hash 值相同的结果分发到对应的 reduce 文件中==。需要结合sort by使用。

注意: Hive要求 distribute by 语句要写在 sort by 语句之前。

3. cluster by

  • 当 distribute by 和 sort by 字段相同时,可以使用 cluster by 方式

  • 除了 distribute by 的功能外,还会对该字段进行排序,所以 cluster by = distribute by + sort by

--以下两种写法等价

insert overwrite local directory '/home/hadoop/hivedata/distribute_sort' 
select * from student distribute  by score sort  by score;


insert overwrite local directory '/home/hadoop/hivedata/cluster' 
select * from student cluster by score;

实践

1. 查询学生的成绩,并按照分数降序排列

select * from student s order by score desc;

2. 按照别名排序

  • 按照学生分数的平均值排序
select s.sid,s.tname, avg(score)  as score_avg  from student s  group by  s.sid,s.tname order by score_avg  desc;

3. 多列排序

  • 按照学生分数和年龄升序排序
select *  from student s order by score,age;

4. 每个 MapReduce 内部排序(Sort By)局部排序

sort by:每个reducer内部进行排序,对全局结果集来说不是排序。

1、设置reduce个数

set mapreduce.job.reduces=3;

2、查看设置reduce个数

set mapreduce.job.reduces;

3、查询成绩按照成绩降序排列

select * from student s sort by s.score;

4、将查询结果导入到文件中(按照成绩降序排列)

insert overwrite local directory '/home/hadoop/hivedata/sort' select * from student s sort by s.score;

5. 先按照学生 sid 进行分区,再按照学生成绩进行排序

1、设置reduce的个数

set mapreduce.job.reduces=3;

2、通过 distribute by 进行数据的分区,将不同的 sid 划分到对应的 reduce 当中去

insert overwrite local directory '/home/hadoop/hivedata/distribute' select * from student distribute by sid sort by score;