Hive中关于排序的几种方法,有必要深入理解其原理。
Order by 全局排序
1)Order By:全局排序,只有一个 Reducer,即使我们在设置set reduceer的数量为多个,但是在执行了order by语句之后,当前此次的运算还是只有1个reducer,因为order by要做的是全局分区。ORDER BY 子句在 SELECT 语句的结尾。
order by 语句的运行效率较低,公司一般是不让用的,加上limit 可以用。
使用 ORDER BY 子句排序 :
ASC(ascend): 升序(默认)
DESC(descend): 降序
(1)查询员工信息按工资升序排列
hive (default)> select * from emp order by sal;
(2) 查询员工信息按工资降序排列
hive (default)> select * from emp order by sal desc;
其中,order by还可以做对多个列进行排序
(3)按照部门和工资升序排序
hive (default)> select ename, deptno, sal from emp order by deptno, sal;
Sort By : 每个 Reduce 内部排序
Sort By:对于大规模的数据集 order by 的效率非常低。在很多情况下,并不需要全局排序,此时可以使用 sort by。
Sort by 为每个 reducer 产生一个排序文件。每个 Reducer 内部进行排序,对全局结果集 来说不是排序。
1)设置 reduce 个数
hive (default)> set mapreduce.job.reduces=3;
2)查看设置 reduce 个数
hive (default)> set mapreduce.job.reduces;
3)根据部门编号降序查看员工信息
hive (default)> select * from emp sort by deptno desc;
4)将查询结果导入到文件中(按照部门编号降序排序)
hive (default)> insert overwrite local directory '/opt/module/data/sortby-result'
select * from emp sort by deptno desc;
查出来的结果类似下图所示:
在每个分区当中,对其进行排序。
Distribute By
Distribute By: 在有些情况下,我们需要控制某个特定行应该到哪个 reducer,通常是为 了进行后续的聚集操作。distribute by 子句可以做这件事。distribute by 类似 MR 中 partition(自定义分区),进行分区,结合 sort by 使用。
对于 distribute by 进行测试,一定要分配多 reduce 进行处理,否则无法看到 distribute by 的效果。
hive (default)> set mapreduce.job.reduces=3; hive (default)> insert overwrite local directory
'/opt/module/data/distribute-result' select * from emp distribute by deptno sort by empno desc;
注意:
distribute by 的分区规则是根据分区字段的 hash 码与 reduce 的个数进行模除后,余数相同的分到一个区。
Hive 要求 DISTRIBUTE BY 语句要写在 SORT BY 语句之前。
有一点是需要特别注意的是: 我之前一直认为,distribute by的字段有多少个不一样的值,就set多少个reducers,自然而然得出的结果就是不同的每一个不同的值都会被分配到每一个对应的reducer中,事实上,不是这样的。他是根据distribute by 后的字段hash码与reduce 的个数进行模数后,再考虑该行要丢到哪个分区,会出现一个分区多个不同的值和一个分区里面是全空的情况。
Cluster By
当 distribute by 和 sort by 字段相同时,可以使用 cluster by 方式。
cluster by 除了具有 distribute by 的功能外还兼具 sort by 的功能, 但是排序只能是升序 排序,不能指定排序规则为 ASC 或者 DESC。
(1)以下两种写法等价
hive (default)> select * from emp cluster by deptno;
hive (default)> select * from emp distribute by deptno sort by deptno;