分桶是将数据集分解成更容易管理的若干部分的另一个技术。
分区针对的是数据的存储路径;分桶针对的是数据文件。
分區主要是為了解決業務問題
分桶主要是為了解決數據傾斜問題,數據的分佈問題,更接近底層mr的partition
分区表(多用)
概述
给数据指定分区表,会在hdfs上根据分区表名创建对应文件夹,文件夹里有原来的数据,文件夹名会成为表的另外一列
一张非分区表不能转化成分区表,分区表要在创建的时候就确认了
使用前提:建立分区后,查询时使用where=’分区指定字段‘可以避免全盘扫描
多级分区:
partition (xxx , yyy):
xxx文件夹,在yyy文件夹里
使用:
DDL
创建分区:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
例子:
注:分区表partitioned by 后面的month不能出现在表名字后面的字段中,代表的是独立字段
create table dept_partition(
deptno int, dname string, loc string
)
partitioned by (month string)
row format delimited fields terminated by '\t';
装载数据
需要指定分区,如果不指定,会默认生成一个_HIVE_DEFAULT_PARTITION分区
方式一:
加载表格式
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201709');
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201708');
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201707');
效果:
方式二:
从已有插入,格式:
insert into default.dept_partition partition(loc="1700") select deptno,dname from dept where loc=1700
DML
分区的增删改查
添加分区
可以用
空格
逗号,分开分区
alter table dept_par add partition(day='2020-10-28') partition(day='2020-10-29') .....
删除分区
只能用逗号删除不同分区
alter table dept_par drop partiton(day='2020-10-29')
查看分区
show partition dept_par
查看分区信息
查看表详情:
desc formatted dept_par/
找到 partition information 主要看由什么分区字段
与创建的文件夹建立联系
这个分区一定要用命令生成,如果通过在hdfs创建文件夹的方式添加是无效的,原因:创建的文件夹没有包含元数据,
除非:创建文件夹后:
再用命令创建同名分区
或使用修复命令:
msck repair table xxx
这条指令和手滑删除外部表后回复数据是一致的。
动态分区调整
hive默认开启
作用:
解决插入麻烦的问题,对比上面的装载数据-从已有插入,格式。
hive3新的动态分区写法:
不需要修改严格模式
insert into default.dept_partiton partition(deptno) select deptno,dname,loc from dept
hive2旧的动态分区写法:
需要修改为非严格模式(默认是严格模式)
set hive.exec.dynamic.partition.mode=nonstrict
insert into default.dept_partition partition(deptno) select dname,loc from dept
对比静态分区:
insert into default.dept_partition partition(loc="1700") select deptno,dname from dept where loc=1700
区别:不需要写partition,和过滤语句
本质:
动态分区是,表中的分区字段数据是什么,分区就是什么,
而静态分区是写死某个分区。
1)开启动态分区参数设置
(1)开启动态分区功能(默认true,开启)
hive.exec.dynamic.partition=true
(2)设置为非严格模式(动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。)
hive.exec.dynamic.partition.mode=nonstrict
(3)在所有执行MR的节点上,最大一共可以创建多少个动态分区。默认1000(少)
hive.exec.max.dynamic.partitions=1000
(4)在每个执行MR的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错。(少)
hive.exec.max.dynamic.partitions.pernode=100
(5)整个MR Job中,最大可以创建多少个HDFS文件。默认100000(少)
hive.exec.max.created.files=100000
(6)当有空分区生成时,是否抛出异常。一般不需要设置。默认false(少)
hive.error.on.empty.partition=false
2)案例实操
需求:将dept表中的数据按照地区(loc字段),插入到目标表dept_partition的相应分区中。
(1)创建目标分区表
建表和插入同时需要partition语句,否则不能实现分区
hive (default)> create table dept_partition(id int, name string) partitioned
by (location int) row format delimited fields terminated by '\t';
(2)设置动态分区
注意这里:insert 进去的是新表(dept_partition),select 的是旧表(dept),所以字段名可以不一样
set hive.exec.dynamic.partition.mode = nonstrict;
hive (default)> insert into table dept_partition partition(location) select deptno, dname, loc from dept;
(3)查看目标分区表的分区情况
hive (default)> show partitions dept_partition;
分桶和分桶表
分桶:
就是查询阶段mr的collect阶段调用partition方法 进行分区,sort by 进行排序
分桶方式:
通过哈希值取余reduce个数
进行分桶
分桶设置:
reduce 的个数设置为-1(最好),让job自行决定需要多少个reduce:有多少个reduce就多少个桶
或者将reduce的个数设置大于等于分桶表的桶数:
分桶表:
说明:
最大好处是加快join的速度,详情请看大表join大表(3),
所以一般分桶不直接用,而是当大表join大表的时候会用到。
建表:(桶的个数不能超过可用CPU的核数,不然执行task时会相互抢占资源 )
需要创建两张分桶表
然后分桶表与分桶表之间进行join,
桶的个数需要保持一致
create table stu_buck(id int, name string)
clustered by(id)
into 4 buckets
row format delimited fields terminated by '\t';
查看表结构
hive (default)> desc formatted stu_buck;
Num Buckets:
导入数据到分桶表中
hive (default)> load data local inpath '/opt/module/datas/student.txt' into table stu_buck;
测试: