Hive | 排序查询【order by/cluster by/distribute by/sort by】
1 order by
order by会对输出的结果进行全局排序,因此底层使用MapReduce引擎执行的时候,只会有一个reducetask执行。如果输出的行数太大,会导致需要很长的时间才能完成全局排序。默认排序顺序为升序(ASC),也可以指定DESC降序。在Hive中,默认NULL空值为最小值。
需要注意的是受hive.mapred.mode的影响,当hive.mapred.mode设置为strict严格模式时,必须使用limit对排序的数据量进行限制,因为数据量很大且只有一个reducetask,会出现OOM或者运行时间超长的情况。
select * from t_usa_covid19_p
where count_date = "2021-01-28" and state ="California"
order by deaths desc
limit 3;
2 cluster by
Hive SQL中cluster by可以根据指定字段将数据分区,每个区内再根据这个字段升序排序(不允许指定排序规则),概括起来就是根据同一个字段,分区排序。分区的规则哈希取余分区,分为几个区取决于reduce task的个数。注意使用cluster by必须人为指定分区的数量(Reduce数量),默认情况下,reduce task的个数由Hive在编译期间自己决定。
--手动设置reduce task个数
set mapreduce.job.reduces = 2;
select * from student cluster by sno;
执行结果如下:分为两个部分,每个部分升序排序。

假如要把学生表数据根据性别分为两个部分,每个分组内根据年龄的倒序排序。cluster by无法完成。而order by更不能在这里使用,因为它是全局排序,一旦使用order by,编译期间就会强制把reduce task个数设置为1。无法满足分组的需求。
3 distribute by + sort by
如果说cluster by的功能是分组排序(同一个字段),那么distribute by + sort by就相当于把cluster by的功能一分为二:distribute by负责分区,sort by负责分组内排序,并且可以是不同的字段。如果distribute by + sort by的字段一样,则此时cluster by=distribute by + sort by。
--手动设置reduce task个数
set mapreduce.job.reduces = 2;
--案例:把学生表数据根据性别分为两个部分,每个分组内根据年龄的倒序排序。
select * from student distribute by sex sort by sage desc;

--下面两个语句执行结果一样
select * from student distribute by sno sort by sno;
select * from student cluster by sno;
4 小结

- order by会对输入做全局排序,因此只有一个reducer,当输入规模较大时,需要较长的计算时间。
- sort by不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。
- distribute by(字段)根据指定字段将数据分到不同的reducer,分发算法是hash散列。
- cluster by(字段) 除了具有distribute by的功能外,还会对该字段进行排序。
sh散列。 - cluster by(字段) 除了具有distribute by的功能外,还会对该字段进行排序。
- 如果distribute和sort的字段是同一个时,此时,cluster by = distribute by + sort by
更多推荐




所有评论(0)