Apache Hive order by与sort by以及distribute by 配合sort by 和cluster by的区别

1.order bysort by以及distribute by 配合sort bycluster by的区别

先记结论:

order by: 全局排序,全局有序,无论数据量多大,只会有一个reducetask运行,所以当数据量比较大的时候,性能会大打折扣。(手动设置reducetask对其没有影响)

sort by: 会根据数据量自动调整reducetask的个数的(hive2.x默认mapreduce.job.reduces值为-1),也可以手动设置个数,sort by是进行局部排序的,只有一个reducetask时,与order by一致,但是当数据量一大时会分成多个reducetask进行执行,性能是会大大提升的。但是只用 sort by的话,相同数据是不会分到一起的,需要配合distribute by一起使用。

distribute by 配合sort by : distribute by用于sort by之前的分区字段的设置,两者配合,能够保证distribute by 后面的字段值相同的被分到同一个分区中。注意此种方式分区的字段和排序的字段可以不一致。即distribute by后面与sort by后面的字段可以不一样。

cluster by: 相当于 distribute by 字段 sort by 字段,即分区字段和局部排序字段必须一样,而且必须是升序,限制比较大。

2.测试证实结论(上面的结论)

我们来看看reducetask的默认数量:

set mapreduce.job.reduces; # 默认 -1

hive 1.x默认是每一个mapreduce任务只有1个reducetask,2.x默认为 -1,即表示它的个数是根据实际的任务量大小动态分配的。(这里先为-1,后面改成3测试结果

1)class表原始数据
hive> select * from class;
OK
tom	7512
tim	7512
kom	7514
kim	7512
jom	7511
jim	7511
lim	7514
rim	7512
sju	7512
tds	7512
jde	7511
jedw	7511
jsd	7514
xjs	7514
jsd	7514
ew	7514
jsew3d	7514
xjews	7514
jsew3d	7514
xjews	7514
je32	7511
lie23e	7514
riwedw	7512
sjdweu	7512
tdsdwe	7512
2) 使用order by 进行排序----reducetask个数1(此时自动获取个数为1)
select * from class order by name desc;

测试结果数据如下:(只有开启1个reducetask)

xjs	7514
xjews	7514
xjews	7514
tom	7512
tim	7512
tdsdwe	7512
tds	7512
sju	7512
sjdweu	7512
riwedw	7512
rim	7512
lim	7514
lie23e	7514
kom	7514
kim	7512
jsew3d	7514
jsew3d	7514
jsd	7514
jsd	7514
jom	7511
jim	7511
jedw	7511
je32	7511
jde	7511
ew	7514
3) 使用sort by 进行测试----reducetask个数1(此时自动获取个数为1)
select * from class sort by name desc;

结果同上面order by 的输出一样,只运行了1个reducetask。至此,你以为sort by 与order by是一致的,那就大错特错了

4) 使用order by 进行测试----reducetask个数为3

下面我调整reducetask个数:

set mapreduce.job.reduces=3;

现在再测试一下order by:

select * from class order by name desc;

结果同上面一样,reducetask个数还是1,似乎没有影响,还是一样全局排序

5) 使用sort by 进行测试----reducetask个数为3
select * from class sort by name desc;
xjews	7514
tdsdwe	7512
tds	7512
sju	7512
sjdweu	7512
rim	7512
lim	7514
lie23e	7514
jsew3d	7514
jsd	7514
jom	7511
jim	7511

xjs	7514
xjews	7514
tim	7512
kom	7514
kim	7512
jsew3d	7514
jedw	7511
jde	7511

tom	7512
riwedw	7512
jsd	7514
je32	7511
ew	7514

从上面数据看,这数据好乱啊,仔细看,我们会发现,上面我用空行隔开的数据内部是有序的,但是是为什么还有相同的数据在不同的部分中(分区中)呢?(xjews在第一部分中出现,在第二部分中也出现)

其实,sort by是做局部排序的,由于这里是3个reducetask,即对应3个mapreduce任务的分区,sort by 只是对着3个分区中的数据进行排序的。那么每个分区的数据是根据什么拿到的呢?实际上是随机的,然后对每一个分区中的数据进行排序输出,结果就如上面所示。

6) 使用sort by配合distribute by进行测试----reducetask个数为3

随意为了避免数据的随机拿取,我们需要让sort by 结合distribute by使用,distribute by是用来为sort by指定分区字段的(说白了就是map的key)相同的key的会被分到一组。

现在再来测试:

select * from class distribute by name sort by name desc;
xjews	7514
xjews	7514
tom	7512
tim	7512
kom	7514
kim	7512
jsd	7514
jsd	7514
jedw	7511

tdsdwe	7512
tds	7512
rim	7512
lim	7514
lie23e	7514
jde	7511
ew	7514

xjs	7514
sju	7512
sjdweu	7512
riwedw	7512
jsew3d	7514
jsew3d	7514
jom	7511
jim	7511
je32	7511

可以看到 两个 xjews 被分到一组了,或许你觉得不具有代表性,你自己可以测试一下,这里的测试数据不太好。

那么为什么有了distribute by 就会根据其后面而定字段划分呢?你完全可以类比于mapreduce的分区,分区的原理是很具map的key来确定的。这里就是name(distribute by后面的)。

如果分区是字符串: 字段值.hashCode % 分区数

如果分区字段是整型:字段值%分区数

这里的分区数与reducetask是一致的,也就是我前面通过设置set mapreduce.job.reduces=3来改变的。在进行分区的时候,它会把上面计算结果相同的放到一个分区,那么久保证了相同数据在同一个分区。

7)测试cluster by-----resucetask个数为3

对于cluster by 的话,由于不能指定排序,只能是升序,所以下面只演示升序结果:

select * from class cluster by name;
jedw	7511
jsd	7514
jsd	7514
kim	7512
kom	7514
tim	7512
tom	7512
xjews	7514
xjews	7514

ew	7514
jde	7511
lie23e	7514
lim	7514
rim	7512
tds	7512
tdsdwe	7512

je32	7511
jim	7511
jom	7511
jsew3d	7514
jsew3d	7514
riwedw	7512
sjdweu	7512
sju	7512
xjs	7514

你可能感兴趣的:(Hive)