Hive中 Order by,Sort by, Distribute by, Cluster by详解
本文的数据基础:
empno | ename | job | mgr | hiredate | sal | comm | deptno |
工号 | 姓名 | 职位 | 老板工号 | 雇佣日期 | 工资 | 不重要 | 部门编号 |
初始计算引擎为tez,而不是默认的MR。
1.Order by
order by的用法和mysql中一模一样,是针对全局排序。此处不进行详述。
2.Sort by
Hive基于Hadoop集群,Sort by为每个reducer产生一个排序文件。每个Reducer内部进行排序,对全局结果集来说不是排序。
既然是说为每个reducer产生一个排序文件,那当然要有两个以上的reducer了。可在hive客户端设置reducer个数,我这里设置为3,意味着会产生三个分区。
注意:不设置这个参数的话,默认reducer个数为1,和order by没区别。
hive (default)> set mapreduce.job.reduces=3;
针对部门编号deptno来一下sort by;
select * from emp sort by deptno desc;
可以看到,上表确实是被分成了三部分,并按大到小排序。
看到这三个分区,有没有什么疑问呢?为何每个分区都会有相同的deptno数据。这个结果说明分区机制并不是按照hadoop中取key的hash值 % reducer个数得到的。下面来看一段英文:
Note: It may be confusing as to the difference between
SORT BY alone of a single column and CLUSTER BY.
The difference is that CLUSTER BY partitions by the field and
SORT BY if there are multiple reducers partitions randomly
in order to distribute data (and load) uniformly across the reducers.
替你们翻译一下:
注意:关于单个列的单独SORT BY与CLUSTER BY之间的区别可能会造成混淆。
区别在于,如果有多个reducer分区,则CLUSTER BY按字段划分,
而SORT BY则是随机划分,以便在reducer上均匀地分布数据(和负载)。
上面这段英文来自hive.apache.org官网
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SortBy
这说明结果的由来是随机的,但并不是每次都是随机,而是通过一种随机算法计算得到,就是说你再排序一次,得到的依然是上面的结果,不信的童鞋可以试一下。
sort by通常和下面要介绍的Distribute by一起使用。
3.Distribute by
Distribute by可以控制某个特定行应该到哪个reducer,通常是为了进行后续的聚集操作。类似MR中partition(自定义分区)。
先给个结论:
Ø distribute by的分区规则是根据分区字段的hash码与reduce的个数进行模除后,余数相同的分到一个区。
下面开搞:
依然设置reducer个数为3:
hive (default)> set mapreduce.job.reduces=3;
再针对deptno字段进行distribute by.
select * from emp distribute by deptno;
结果如下:
结果有点出人意料,数字的hash值是其本身,按照distribute by的分区规则,那应该是10在1号分区,20在2号分区,30在0号分区(请忽略null,脏数据)。这里为什么只有两个分区,20,30堆在一起了?我们来验证一下是否是真的堆在一起了,将查询的文件输出到本地:
insert overwrite local directory '/opt/module/hive/datas/dis_by' select * from emp distribute by deptno;
查看datas文件夹:
[shy@hadoop dis_by]$ ll
总用量 8
-rw-r--r--. 1 shy shy 546 7月 30 22:21 000000_0
-rw-r--r--. 1 shy shy 139 7月 30 22:21 000001_0
确实是只有两个文件,内容:
[shy@hadoop dis_by]$ cat 000000_0
\N\N\N\N\N\N\N\N
7902FORDANALYST75661981-12-33000.0\N20
7900JAMESCLERK76981981-12-3950.0\N30
7876ADAMSCLERK77881987-5-231100.0\N20
7844TURNERSALESMAN76981981-9-81500.00.030
7788SCOTTANALYST75661987-4-193000.0\N20
7698BLAKEMANAGER78391981-5-12850.0\N30
7654MARTINSALESMAN76981981-9-281250.01400.030
7566JONESMANAGER78391981-4-22975.0\N20
7521WARDSALESMAN76981981-2-221250.0500.030
7499ALLENSALESMAN76981981-2-201600.0300.030
7369SMITHCLERK79021980-12-17800.0\N20
确实是20, 30堆在一起了。
这是因为目前用的计算引擎是tez!它会自动进行优化。
现在我们来更改一下引擎:
set hive.execution.engine=mr;
再执行一次distribute by排序:
select * from emp distribute by deptno;
结果很明确:
可以再加上sort by,分区内的empno进行排序:
select * from emp distribute by deptno sort by empno;
结果:
所以,distribute by和sort by的区别是一个按规则分区,一个随机分区并排序。
4.Cluster by
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。当distribute by和sort by字段相同时,可以使用clusterby方式。
以下两种写法等价
hive (default)> select * from emp cluster by deptno;
hive (default)> select * from emp distribute by deptno sort by deptno;
rby方式。