order by
order by会对输入做全局排序,因此只有一个Reducer(多个Reducer无法保证全局有序),然而只有一个Reducer,会导致当输入规模较大时,消耗较长的计算时间,在生产环境中遇到数据量较大的情况,一般无法成功。
sort by
sort by不是全局排序,其在数据进入reducer前完成排序,因此,如果用sort by进行排序,并且设置mapreduce.job.reduces 多于1个,则sort by只会保证每个reducer的输出有序,但不保证全局有序。
sort by的数据只能保证在同一个reduce中的数据可以按指定字段排序。使用sort by你可以指定执行的reduce个数(通过set mapreduce.job.reduces=n来指定),对输出的数据再执行归并排序,即可得到全部结果。
distribute by
distribute by是控制在map端如何拆分数据给reduce端的。hive会根据distribute by后面列,对应reduce的个数进行分发,默认是采用hash算法。sort by为每个reduce产生一个排序文件。
在有些情况下,你需要控制某个特定行应该到哪个reducer,这通常是为了进行后续的聚集操作。distribute by刚好可以做这件事。因此,distribute by经常和sort by配合使用。
注意
distribute by 的分区规则是根据分区字段的 hash 码与 reduce 的个数进行模除后, 余数相同的分到一个区,也就意味着同一个分区中的分区字段不一定相同。
Hive 要求 distribute by 语句要写在 sort by 语句之前,因为,sort by 是对分区中排序
cluster by
当 distribute by 和 sorts by 字段相同时,可以使用 cluster by 方式。
cluster by 除了具有 distribute by 的功能外还兼具 sort by 的功能。但是排序只能是升序排序,不能指定排序规则为 ASC 或者 DESC。
在分区和排序字段相同的前提下,他等价于 distribute by 和sort by 的一个简写方式。
演练
数据和建表
tb_loc(地域表)
代码语言:javascript复制2001 NewYork
2002 Boston
2003 Dallas
2004 Chicago
create table tb_loc(
loc int,
locname string
)
row format delimited fields terminated by 't';
tb_dept(部门表)
代码语言:javascript复制10 ACCOUNTING 2001
20 RESEARCH 2002
30 SALES 2003
40 OPERATIONS 2004
create table tb_dept(
deptno int,
dname string,
loc int
)
row format delimited fields terminated by 't';
tb_emp(员工表)
代码语言:javascript复制7369 SMITH CLERK 7902 1980-12-17 800.00 NULL 20
7499 ALLEN SALESMAN 7698 1981-02-20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981-02-22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981-04-02 2975.00 NULL 20
7654 MARTIN SALESMAN 7698 1981-09-28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981-05-01 2850.00 NULL 30
7782 CLARK MANAGER 7839 1981-06-09 2450.00 NULL 10
7788 SCOTT ANALYST 7566 1987-04-19 3000.00 NULL 20
7839 KING PRESIDENT NULL 1981-11-17 5000.00 NULL 10
7844 TURNER SALESMAN 7698 1981-09-08 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987-05-23 1100.00 NULL 20
7900 JAMES CLERK 7698 1981-12-03 950.00 NULL 30
7902 FORD ANALYST 7566 1981-12-03 3000.00 NULL 20
7934 MILLER CLERK 7782 1982-01-23 1300.00 NULL 10
7934 TOM CLERK 7782 1982-01-23 1200.00 NULL 50
7934 JACK CLERK 7782 1982-01-23 1100.00 NULL 60
代码语言:javascript复制create table tb_emp(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal float,
comm float,
deptno int
)
row format delimited fields terminated by 't';
导入数据
代码语言:javascript复制load data local inpath '/hivedata/dept.txt' into table tb_dept;
load data local inpath '/hivedata/emp.txt' into table tb_emp;
load data local inpath '/hivedata/loc.txt' into table tb_loc;
Order By
代码语言:javascript复制-- 全局排序,只有一个reduce
hive (default)> select * from tb_epm order by sal;
-- 按照别名排序
hive (default)> select ename,sal*2 as 2sal from tb_emp order by 2sal;
-- 多个列排序
hive (default)> select ename, deptno, sal from tb_emp order by deptno, sal;
每个 Reduce 内部排序(Sort By)
代码语言:javascript复制-- 设置 reduce 个数
hive (default)> set mapreduce.job.reduces=3;
-- 查看设置 reduce 个数
hive (default)> set mapreduce.job.reduces;
-- 每个reduce内部按照deptno 降序排列
hive (default)> select * from tb_emp sort by deptno desc;
-- 将查询结果导入到文件中
hive (default)> insert overwrite local directory
'/hivedata/sortby-result'
select * from tb_emp sort by deptno desc;
Distribute By
代码语言:javascript复制--先按照部门编号分区,再按照员工编号降序排序
hive (default)> set mapreduce.job.reduces=3;
hive (default)> insert overwrite local directory
'/hivedata/distribute-result'
select * from tb_emp distribute by deptno sort by empno desc;
distribute by 的分区规则是根据分区字段的 hash 码与 reduce 的个数进行模除后, 余数相同的分到一个区。
注意:DISTRIBUTE BY 语句要写在 SORT BY 语句之前
Cluster By
当 distribute by 和 sorts by 字段相同时,并且排序为升序时,可以使用 cluster by 方式。
cluster by = distribute by sorts by
只能是升序排序,不能指定排序规则为 ASC 或者 DESC。
代码语言:javascript复制-- 下面这两个的结果是一样的
-- 满足条件,即cluster by 和 sort by 的字段相同,并且是升序排列
hive (default)> select * from tb_emp cluster by deptno;
hive (default)> select * from tb_emp distribute by deptno sort by deptno;