Hive排序、分区和分桶
排序
全局排序(Order by)
对整个输出结果集进行排序,只会产生一个Reduce
每个Reduce内部排序(Sort by)
Sort By:对于大规模的数据集order by的效率非常低。在很多情况下,并不需要全局排序,此时可以使用sort by。
Sort by为每个reducer产生一个排序文件。每个Reducer内部进行排序,对全局结果集来说不是排序。
Sorby 会把多个排好序的Reduce输出文件拼接在一起,形成一张表
一般会配合Dirtrubute By使用,不会单独使用
分区(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)> select * from emp distribute by deptno sort by sal desc;
-
distrubute by的分区规则是根据分区字段的hash码与reduce个数进行取模后得到的
-
Hive要求distribute by语句要写在sort by语句之前
-
演示完以后mapreduce.job.reduce的值记得改回默认值-1
分区排序(Cluster By)
很少使用Cluster by,因为大多数情况下,分区和分组字段不会相同
- 当distribute by和sort by字段相同时,可以使用cluster by方式。
- cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。
分区表
Hive里有个很大毛病 它没有索引 ,它每次扫描都只能扫描全表
分区表测试
create table dept_partition(
deptno int, dname string, loc string
)
partitioned by (day string)
row format delimited fields terminated by '\t';
load data local inpath '/opt/module/hive/datas/dept_20200401.log' into table dept_partition ; --错误的 (虽然能运行)
load data local inpath '/opt/module/hive/datas/dept_20200401.log' into table dept_partition partition(day='20200401');
load data local inpath '/opt/module/hive/datas/dept_20200402.log' into table dept_partition partition(day='20200402');
load data local inpath '/opt/module/hive/datas/dept_20200403.log' into table dept_partition partition(day='20200403');
分区表
其实就是在分文件夹 , 但是他又可以当做一个列来使用,帮助我们定位数据位置,不需要再暴力扫描全表了
创建的时候 分区字段一定不能是表里面存在的列
create table dept_partition2(
deptno int, dname string, loc string
)
partitioned by (deptno string)
row format delimited fields terminated by '\t';
增
alter table dept_partition add partition(day = '20200404');
alter table dept_partition add partition(day = '20200405')partition(day='20200406');
查
show partitions dept_partition;
show partitions dept; --不能查一个不是分区表的表
desc dept_partition;
desc formatted dept_partition;
删(对于外部表 只能删分区的元数据信息 hdfs文件夹会保留)
alter table dept_partition drop partition(day = '__HIVE_DEFAULT_PARTITION__')
alter table dept_partition drop partition(day='20200405'),partition(day='20200406')
二级分区
导入数据
load data local inpath '/opt/module/hive/datas/dept_20200401.log' into table
dept_partition2 partition(day='20200401',hour = '13');
load data local inpath '/opt/module/hive/datas/dept_20200402.log' into table
dept_partition2 partition(day='20200401',hour = '14');
load data local inpath '/opt/module/hive/datas/dept_20200403.log' into table
dept_partition2 partition(day='20200402',hour = '13');
--增
alter table dept_partition2 add partition(day = '20200403',hour='13') ;
--删
alter table dept_partition2 drop partition(day = '20200401') ;
让分区表和下面的分区文件夹产生关系三种方式
1.修复(能够自动扫描对应的表的文件夹下面符合规则的文件夹并添加元数据)
msck repair table dept_partition2;
2.手动添加一个分区信息
alter table dept_partition2 add partition(day = '20200404',hour='13') ;
3.load 数据到一个指定分区里面
load data local inpath '/opt/module/hive/datas/dept_20200401.log' into table
dept_partition2 partition(day='20200405',hour='13');
7.1.6动态分区(能够根据数据中的最后的列 来放到不同分区目录下)
load data local inpath '/opt/module/hive/datas/dept.txt' into table dept_partition_dy;
load data local inpath '/opt/module/hive/datas/dept_20200501.log' into table dept_partition;
--二级分区
create table dept_partition_dy2(id int) partitioned by (name string,loc int) row format delimited fields terminated by '\t';
load data local inpath '/opt/module/hive/datas/dept.txt' into table dept_partition_dy2;
insert into table dept_partition_dy2 partition(name,lo) select deptno, dname,loc from dept;
但是要记住 严格模式 是在你指定partition 时候才有效果
分桶(分的是你具体的数据)
create table stu_buck(id int, name string)
clustered by(id)
into 4 buckets
row format delimited fields terminated by '\t';
7.2.1创建一个又分区又分桶的表
create table stu_buck_part(id int, name string)
partitioned by (day string)
clustered by(id)
into 4 buckets
row format delimited fields terminated by '\t';
load data local inpath '/opt/module/hive/datas/student.txt' into table stu_buck_part partition(day = '20200923')
7.2.2分区和分桶的区别
1. 分区分的是目录 分桶分的是具体的数据
2. 分区字段必不能再创建表的字段里 分桶字段必在创建的字段里