hive中order by、sort by、distribute by、cluster by的区别详解

1. order by

  在hive中order by是进行全局排序的,这也就是说会最后会在一个reduce
中进行统一的排序,所以说使用order by进行全局排序尽量不要对数据量很
大 的表进行全局排序,这样效率会很低,会对进行排序的那一个reduce所在
的节点造成内存压力。
使用order by会受到如下属性的约束:
set hive.mapred.mode=nonstrict;
set hive.mapred.mode=strict;
  默认是在nonstrict模式下的,如果在strict模式下使用order by的话必
须使用limit关键字,这里只是讲解一下order by的排序是在哪里进行的,
就不举例子说明了,总之使用order by进行排序的时候要注意数据量的问题
具体的使用规则在之前的文章中已经进行了讲解,如果有想要了解的可通过
如下网址看一下:

order by详细讲解

2. sort by

  hive中的sort by是进行的区内排序,如果指定了reduce的个数唯一,那
么排序的结果就是全局排序,如果有多个reduce就是区内有序,全局无序,
这个要根据个人的需求来使用。
使用语法如下:
select * from tb_name sort by column_name;
数据表如下:
goods gtype price
口香糖 食品 10
薯片 食品 20
巧克力 食品 30
蛋糕 食品 40
薯条 食品 50
饼干 食品 60
面包 食品 70
月饼 食品 80
方便面 食品 90
洗衣粉 日用品 11
洗衣液 日用品 21
洗洁精 日用品 31
拖布 日用品 41
毛巾 日用品 51
卫生纸 日用品 61
水杯 日用品 71
水壶 日用品 81
椅子 日用品 91
电视 电器 12
电脑 电器 22
冰箱 电器 32
冰柜 电器 42
洗衣机 电器 52
小太阳 电器 62
电暖器 电器 72
电磁炉 电器 82
空调 电器 92
热水器 电器 102
先将reduce的个数设置为1
set mapred.reduce.tasks=1;
结果数据如下:
goods gtype price
口香糖 食品 10
洗衣粉 日用品 11
电视 电器 12
薯片 食品 20
洗衣液 日用品 21
电脑 电器 22
巧克力 食品 30
洗洁精 日用品 31
冰箱 电器 32
蛋糕 食品 40
拖布 日用品 41
冰柜 电器 42
薯条 食品 50
毛巾 日用品 51
洗衣机 电器 52
饼干 食品 60
卫生纸 日用品 61
小太阳 电器 62
面包 食品 70
水杯 日用品 71
电暖器 电器 72
月饼 食品 80
水壶 日用品 81
电磁炉 电器 82
方便面 食品 90
椅子 日用品 91
空调 电器 92
热水器 电器 102
从结果可以看出来当将reduce的个数设置为1的时候,使用sort by进
行排序结果是全局有序的。

现在将reduce的个数设置为3
set mapred.reduce.tasks=3;
结果数据如下:
goods gtype price rn
热水器 电器 102 1
空调 电器 92 2
电磁炉 电器 82 3
电暖器 电器 72 4
小太阳 电器 62 5
洗衣机 电器 52 6
冰柜 电器 42 7
冰箱 电器 32 8
电脑 电器 22 9
电视 电器 12 10
椅子 日用品 91 11
水壶 日用品 81 12
水杯 日用品 71 13
卫生纸 日用品 61 14
毛巾 日用品 51 15
拖布 日用品 41 16
洗洁精 日用品 31 17
洗衣液 日用品 21 18
洗衣粉 日用品 11 19
方便面 食品 90 20
月饼 食品 80 21
面包 食品 70 22
饼干 食品 60 23
薯条 食品 50 24
蛋糕 食品 40 25
巧克力 食品 30 26
薯片 食品 20 27
口香糖 食品 10 28
  从结果数据中可以看出来从行号'rn'的1~10中的数据是有序的,11~19
中的数据是有序的,20~28中的数据是有序的都是倒序,但是全局是无序的,
所以在使用sort by的时候一定要根据需求来使用,否则最后的结果可能并
不是我们想要的结果。

3. distribute by

  在hive中distribute by是控制map中的数据是如何分发的,使用的hash
计算,使用distribute by指定字段就可以使map端按照执行的字段进行hash
分区,相同的key可以被分到一个reduce中,但是单独使用distribute by
不能保证数据是有序的,所以一般配合sort by来使用。

单独使用语法如下:
select * from tb_name distribute by column_name;
单独使用的结果数据如下:
goods gtype price
口香糖 食品 10
薯片 食品 20
巧克力 食品 30
蛋糕 食品 40
薯条 食品 50
饼干 食品 60
面包 食品 70
月饼 食品 80
方便面 食品 90
毛巾 日用品 51
椅子 日用品 91
水壶 日用品 81
水杯 日用品 71
卫生纸 日用品 61
拖布 日用品 41
洗洁精 日用品 31
洗衣液 日用品 21
洗衣粉 日用品 11
热水器 电器 102
电脑 电器 22
冰箱 电器 32
冰柜 电器 42
洗衣机 电器 52
小太阳 电器 62
电视 电器 12
电暖器 电器 72
电磁炉 电器 82
空调 电器 92
很清晰的可以看出在电器商品类中的价格是无序的。

配合sort by使用的如法如下:
select 
  * 
from tb_name
distribute by column_name1 
sort by column_name2;
  语法中的字段名字"column_name1"和"column_name2"是可以不相同的,
也可以是相同的,这个要看在使用distribute byf分区之后想要根据哪个
字段进行sort by排序。
  这里的结果数据就不展示了,不同分区中的数据肯定是有序的,展示的意
义不大。

cluster by

  hive中的cluster的作用其实就相当与distribute by和sort by结合使
用,不过使用cluster by不能指定排序规则(asc,desc),只能是升序排序,
同时在使用cluster by进行排序的时候没办法像distribute by和sort by
的组合那样可以灵活的指定在分区后根据哪个字段进行排序。
  相信这个时候我们有这样的一个疑问"cluster by存在意义是什么?使用
某个字段分区,再根据这个字段排序意义在哪里?",当这个字段中的数据
值的种类大于分区数的时候就有意义了,就拿我的测试数据举例,假如商品
的种类有1000种,但 reduce的个数只有30个,这个时候cluser by的使用
就有意义了,相信说到这里大家应该都能明白了。

使用语法如下:
select * from tb_name cluster by column_name;
  在这里要跟大家说一下,如果在cluster by后面添加了多个字段,那么在
分 区的时候就会根据这几个字段和reduce的个数来计算hash了分区,如果
在使用cluster by的时候一定要注意这个特点。

在这给大家举个测试的例子,测试sql如下:
select * from t_test cluster by gtype,price;
测试结果数据如下:
goods gtype price
洗衣粉 日用品 11
拖布 日用品 41
水杯 日用品 71
电视 电器 12
冰柜 电器 42
电暖器 电器 72
热水器 电器 102
口香糖 食品 10
蛋糕 食品 40
面包 食品 70
洗衣液 日用品 21
毛巾 日用品 51
水壶 日用品 81
电脑 电器 22
洗衣机 电器 52
电磁炉 电器 82
薯片 食品 20
薯条 食品 50
月饼 食品 80
洗洁精 日用品 31
卫生纸 日用品 61
椅子 日用品 91
冰箱 电器 32
小太阳 电器 62
空调 电器 92
巧克力 食品 30
饼干 食品 60
方便面 食品 90
  通过结果数据可以看到,这个分区似乎有些乱了,但是仔细看看数据的
话可以看出来这是根据gtype和price两个字段分区结果,就拿"日用品",
这个种类举例子,我们看一下结果表中的前三个日用品后面的价格,可
以看到,分别是"11,41,71",在看看中间部分的日用品的价格分别是"21,
51,81",最后面三个日用品的价格是"31,61,91",大家可以发现这三组价格
中的数据组内和3取模得到的结果都是一样的,组间取模都是不同的,所以
可以很清晰看出是将"日用品"类的商品分散到了三个reduce中进行排序的。
  举这个例子是为了让大家在使用cluster by的时候一定要注意这个特点,
避免踩坑。

猜你喜欢

转载自blog.csdn.net/AnameJL/article/details/112548928