文章目录
1.distribute by hash分发到不同分区1.1实验1.2使用场景
2. sort by 局部排序2.1 设置reduce job数对sort by有效果2.2 直接sort by会出现数据分布不均匀的分区内排序2.3 sort by与distribute by 联合使用实现分区内有序
3.cluster by3.1 cluster by 等价于 distribute by+ sort by(distribute和sort字段相同)3.2 distribute by+sort by 比 cluster by 更加灵活
4.order by4.1 全局排序的特点4.2 使用场景
5.总结
1.distribute by hash分发到不同分区
分区规则是根据分区字段的hash码与reduce的个数进行模除后,余数相同的分到一个区。
1.1实验
hive (default)> select * from empt;
OK
empt.empno empt.ename empt.job empt.mgr empt.hiredate empt.sal empt.comm empt.deptno
7566 JONES MANAGER 7863 1980-12-17 2975.0 0 20
7499 NULL NULL NULL NULL NULL NULL NULL
7369 SMITH CLERK 7902 1980-12-17 800.0 0 20
7499 ALLEN SALESMAN 7968 1980-12-17 1600.0 300 20
set mapreduce.job.reduces=3;
set hive.merge.mapredfiles=false;
insert overwrite table empt select * from empt distribute by empno;
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000000_0
7566,JONES,MANAGER,7863,1980-12-17,2975.0,0,20
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000001_0
7369,SMITH,CLERK,7902,1980-12-17,800.0,0,20
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000002_0
7451,\N,\N,\N,\N,\N,\N,\N
7499,\N,\N,\N,\N,\N,\N,\N
7499,ALLEN,SALESMAN,7968,1980-12-17,1600.0,300,20
7566%3=0 在文件000000_0中
7396%3=1 在文件000001_0中
7499%3=2 在文件000002_0中
1.2使用场景
a.distribute by 和 order by 不能一起使用,因为前者是分桶,后者是全局排序,有冲突
hive (default)> select * from empt distribute by empno order by empno;
FAILED: ParseException line 1:39 missing EOF at 'order' near 'empno'
b.kylin构建cube的第二步中使用到distributed by
Redistribute Flat Hive Table
重新分发数据
第一步产出在HDFS上面的数据,文件大小可能会存在分布不均匀的情况:
1.map task ==> 大的文件 ==> 慢
2.map task ==> 小的文件 ==> 快
INSERT OVERWRITE TABLE \`kylin_intermediate_ruozedata_user_click_cube_56d719e1_e45a_ec49_1538_d5c5313b82ee\` SELECT * FROM \`kylin_intermediate_ruozedata_user_click_cube_56d719e1_e45a_ec49_1538_d5c5313b82ee\` DISTRIBUTE BY DW_USER_CLICK_D_DAY,DW_USER_CLICK_D_PROVINCE_ID,DW_USER_CLICK_D_CITY_ID;
通过distributed by语法对数据进行重新分发 + mapreduce.job.reduces
最终达成的效果:使得最终的数据分布非常均匀,且毫无规律
2. sort by 局部排序
2.1 设置reduce job数对sort by有效果
set mapreduce.job.reduces=1;
set hive.merge.mapredfiles=false;
insert overwrite table empt select * from empt sort by empno;
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000000_0
7369,SMITH,CLERK,7902,1980-12-17,800.0,0,20
7499,ALLEN,SALESMAN,7968,1980-12-17,1600.0,300,20
7499,\N,\N,\N,\N,\N,\N,\N
7566,JONES,MANAGER,7863,1980-12-17,2975.0,0,20
2.2 直接sort by会出现数据分布不均匀的分区内排序
set mapreduce.job.reduces=3;
set hive.merge.mapredfiles=false;
insert overwrite table empt select * from empt sort by empno;
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000000_0
empty
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000001_0
7499,\N,\N,\N,\N,\N,\N,\N
7499,ALLEN,SALESMAN,7968,1980-12-17,1600.0,300,20
7566,JONES,MANAGER,7863,1980-12-17,2975.0,0,20
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000002_0
7369,SMITH,CLERK,7902,1980-12-17,800.0,0,20
2.3 sort by与distribute by 联合使用实现分区内有序
Hive要求DISTRIBUTE BY语句要写在SORT BY语句之前。
set mapreduce.job.reduces=3;
set hive.merge.mapredfiles=false;
# 默认分区内升序,此处使用降序
insert overwrite table empt select * from empt distribute by empno sort by empno desc;
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000000_0
7566,JONES,MANAGER,7863,1980-12-17,2975.0,0,20
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000001_0
7369,SMITH,CLERK,7902,1980-12-17,800.0,0,20
# 分区内降序
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000002_0
7499,\N,\N,\N,\N,\N,\N,\N
7499,ALLEN,SALESMAN,7968,1980-12-17,1600.0,300,20
7451,\N,\N,\N,\N,\N,\N,\N
3.cluster by
3.1 cluster by 等价于 distribute by+ sort by(distribute和sort字段相同)
distribute by empno sort by empno 等价于 cluster by empno
distribute by empno sort by empno asc 等价于 cluster by empno
set mapreduce.job.reduces=3;
set hive.merge.mapredfiles=false;
# cluster by 后面可以加cluster by empno desc.默认是升序 asc,如果要降序 与 distribute by empno sort by empno desc 模式相同效果
insert overwrite table empt select * from empt cluster by empno
3.2 distribute by+sort by 比 cluster by 更加灵活
例如:distribute by 字段和sort by 字段可以不一样 ,这里按照empno进行分区,按照ename进行分区内排序
set mapreduce.job.reduces=3;
set hive.merge.mapredfiles=false;
insert overwrite table empt select * from empt distribute by empno sort by ename desc;
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000000_0
7566,JONES,MANAGER,7863,1980-12-17,2975.0,0,20
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000001_0
7369,SMITH,CLERK,7902,1980-12-17,800.0,0,20
# 通过ename降序
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000002_0
7499,ALLEN,SALESMAN,7968,1980-12-17,1600.0,300,20
7499,\N,\N,\N,\N,\N,\N,\N
7451,\N,\N,\N,\N,\N,\N,\N
4.order by
4.1 全局排序的特点
全局排序,默认升序,即使想开3个reduce,最终还是一个reduce,因为是全局排序,如果有多个输出文件实现不了全局排序.
hive (default)> set mapreduce.job.reduces=3;
hive (default)> set hive.merge.mapredfiles=false;
hive (default)> insert overwrite table empt select * from empt order by empno;
# 一个hdfs输出文件,默认升序
[root@hadoop logs]# hdfs dfs -cat /hive/db/empt/000000_0
7369,SMITH,CLERK,7902,1980-12-17,800.0,0,20
7499,ALLEN,SALESMAN,7968,1980-12-17,1600.0,300,20
7499,\N,\N,\N,\N,\N,\N,\N
7566,JONES,MANAGER,7863,1980-12-17,2975.0,0,20
4.2 使用场景
(1) 数据量不太大(如10G) 或 对处理后的结果数据(数据量不大) 进行全局排序,可直接使用order by
(2) 在实际生产中,数据量很大(比如100G),如果直接使用order by,会导致只有一个reduce处理,这么大的数据,会出现很慢的情况。
比如对全世界60多亿人的年消费金额进行降序排序找出Top10,可以采用先sort by 在局部排序中找到前10 ,再进行order by 全局排序中找到前10.简单来说,全局排序中的Top10一定出自于局部排序中的Top10.
select * from
(select * from consumer sort by consumer_amount desc limit 10) a
order by consumer_amount desc limit 10;
注意:生产中不要使用 * 进行模糊匹配,特别是hive中使用列式存储parquent等格式,会对性能造成极大影响。
5.总结
1. order by 全局排序 不能和distribute by 一起使用
2. sort by 局部排序,一般要和distribute by 一起使用,如果没有分桶那么就是全局排序
3. distribute by 对查询的结果进行分布,但不是排序
4. cluseter by 对查询的结果进行分布,然后每个桶内只能是按照自然序排序