HIVE中,order by、sort by、 distribute by和 cluster by区别,以及cluster by有什么意义
1. oreder by
主要是做全局排序。
只要hive的sql中指定了order by,那么所有的数据都会到同一个reducer进行处理(不管有多少map,也不管文件有多少的block,只会启动一个reducer )。但是对于大量数据这将会消耗很长的时间去执行。
这里跟传统的sql还有一点区别:如果指定了hive.mapred.mode=strict(默认值是nonstrict),这时就必须指定limit来限制输出条数。因为:所有的数据都会在同一个reducer端进行,数据量大的情况下可能不能出结果,那么在这样的严格模式下,必须指定输出的条数。
2. sort by
每个reduce端都会进行排序,也就是局部有序,可以指定多个reduce。
同时,如果想测试一下执行的效果,建议将输出结果保存到本地,并调整reduce的数量。(我设置成3个)
将查询结果保存到本地:
insert overwrite
local directory '/home/data'
select * from stu sort by grade desc;
调整reduce的数量:
set mapreduce.job.reduce=3;
查看reduce的数量:
set mapreduce.job.reduce;
但是,只使用sort by的情况下,分区是随机分的。
3. distribute by
指定分区原则。通常和sort by一起用,distribute by必须要写在sort by之前。
理解成:按照XX字段分区,再按照XX字段排序
举个例子:
只按照grade字段排序,但是不指定分区字段:
select * from stu sort by grade;
先按照class分区,再按照grade排序:
select * from stu distribute by class sort by grade;
4. cluster by
当distribute by 和 sort by 所指定的字段相同时,即可以使用cluster by。
注意:cluster by指定的列只能是降序,不能指定asc和desc。
举个例子:
select * from stu distribute by class sort by class
等价于:
select * from stu cluster by class
---------------------------------------------分割线---------------------------------------------
再举个例子:
select * from stu distribute by class sort by class,name
等价于
select * from stud distribute cluster by class sort by name
5. cluster by有什么意义?
cluster by是hive中的,mysql等数据库中是没有的,为什么hive会出现cluster by呢?
order by
当需要对数据排序时,我们可以使用order by。但使用order by意味着对所有数据进行排序,即:无论有多少个map,无论有多少数据量,都只用一个reduce。这会消耗极大的时间,且数据量大时,对资源消耗也极为巨大。
这种情况肯定是不能忍受的,但又没有什么好的解决办法,退而求其次,不要求全局有序,只要求局部有序,也是一种解决办法。于是:sort by出现了。
sort by
使用sort by时,会有多个reduce。每个reduce端都会进行排序,但这时,每个reduce的数据是有序的,但数据全局上看依然是无序的。也就是局部有序,整体无序。
distribute by
使用sort by时,数据是局部有序,整体无序。但这时候,哪些数据进入同一个reduce是随机的,不可把控的。所以可以使用 distribute by 来指定哪些数据进入同一个reduce。
也就是说,我们可以指定哪些数据进入到同一个reduce中,然后这些数据进行排序。
cluster by
等价于 distribute by + sort by
举个例子
举个栗子:某学校对学生成绩进行排序。
select * from t_score order by grade
-- 因为使用了order by,只有一个reduce。
distribute by 、 sort by
假设学生太多,数据太多,无法使用order by进行全局排序
这时候我们可以要求学生的成绩按照专业进行排序,不要求在全校内排序。即:
select * from t_score
distribute by major sort by grade
-- 因为没有使用order by,所以这时可以有多个reduce。
但是,如果reduce的数量小于专业的数量,就会有多个专业在一个reduce中处理的情况,这时候,如果还是distribute by major sort by grade,就会乱序。即:多个专业分到一个区,且直接按照分数排序。
对于这种情况,我们需要先按照专业排序,再按照分数排序。
select * from t_score
distribute by major sort by major, grade
-- 因为没有使用order by,所以这时可以有多个reduce。
其它写法
在我印象里,之前是支持这种写法的:
select * from t_score
cluster by major sort by grade
但是刚才试了一下(2.几版本的hive),不支持这种写法。
test
CREATE TEMP VIEW person (name, age)
AS VALUES ('Zen Hui', 25),
('Anil B', 18),
('Shone S', 16),
('Mike A', 25),
('John A', 18),
('Jack N', 16);
-- Reduce the number of shuffle partitions to 2 to illustrate the behavior of CLUSTER BY
.
-- It's easier to see the clustering and sorting behavior with less number of partitions.
SET spark.sql.shuffle.partitions = 2;
-- Select the rows with no ordering. Please note that without any sort directive, the results
-- of the query is not deterministic. It's included here to show the difference in behavior
-- of a query when CLUSTER BY
is not used vs when it's used. The query below produces rows
-- where age column is not sorted.
SELECT age, name FROM person;
16 Shone S
25 Zen Hui
16 Jack N
25 Mike A
18 John A
18 Anil B
-- Produces rows clustered by age. Persons with same age are clustered together.
-- In the query below, persons with age 18 and 25 are in first partition and the
-- persons with age 16 are in the second partition. The rows are sorted based
-- on age within each partition.
SELECT age, name FROM person CLUSTER BY age;
18 John A
18 Anil B
25 Zen Hui
25 Mike A
16 Shone S
16 Jack N
疑问解答
“cluster by 的字段只是参考分区字段,而非严格的按此字段分区”
可以这么说吧,分区字段的目的不是说按照其枚举值数量产生对应数量的reducer个数,而是为了让同一个key进入同一个reducer中,这是基本的要求,是聚合的基础
解决数据倾斜
distribute by可以实现打乱数据从而解决数据倾斜的效果,但是解决以后数据是无序的,使用cluster by可以在解决数据倾斜的效果之上实现局部有序。
方便查看输出文件
hive可以将查询结果保存到hdfs上,数据量太大且只有一个文件时,查看和传输都很不方便。如果按照固定的大小或条数分开保存,又会出现数据不连贯的情况。
这时候,使用cluster by,既可以生成多个文件,又可以保证数据局部有序且连贯。
连贯的意思是:假设我看一个学校的学生的成绩,重点关注专业。当人为或使用其他办法(标准是:固定的大小或条数分开保存)分片保存数据时,就会出现某专业的学生出现在多个文件中,对查看数据很不友好。