分桶是将数据集分解成更容易管理的若干部分的另一个技术。
分区针对的是数据的存储路径;分桶针对的是数据文件。

分區主要是為了解決業務問題
分桶主要是為了解決數據傾斜問題,數據的分佈問題,更接近底層mr的partition

分区表(多用)

概述

给数据指定分区表,会在hdfs上根据分区表名创建对应文件夹,文件夹里有原来的数据,文件夹名会成为表的另外一列
一张非分区表不能转化成分区表,分区表要在创建的时候就确认了

使用前提:建立分区后,查询时使用where=’分区指定字段‘可以避免全盘扫描

理解:就相当于加了索引

多级分区:

partition (xxx , yyy):
xxx文件夹,在yyy文件夹里
image.png

使用:

DDL

创建分区:

  1. CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
  2. [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]

例子:
注:分区表partitioned by 后面的month不能出现在表名字后面的字段中,代表的是独立字段

  1. create table dept_partition(
  2. deptno int, dname string, loc string
  3. )
  4. partitioned by (month string)
  5. row format delimited fields terminated by '\t';

装载数据

需要指定分区,如果不指定,会默认生成一个_HIVE_DEFAULT_PARTITION分区
方式一:
加载表格式

  1. hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201709');
  2. hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201708');
  3. hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201707');

效果:
image.png
image.png

方式二:
从已有插入,格式

  1. insert into default.dept_partition partition(loc="1700") select deptno,dname from dept where loc=1700

DML

分区的增删改查

添加分区
可以用
空格
逗号,分开分区

  1. alter table dept_par add partition(day='2020-10-28') partition(day='2020-10-29') .....

删除分区
只能用逗号删除不同分区

  1. alter table dept_par drop partiton(day='2020-10-29')

查看分区

  1. show partition dept_par

image.png

查看分区信息
查看表详情:

  1. desc formatted dept_par/

找到 partition information 主要看由什么分区字段
image.png

与创建的文件夹建立联系

这个分区一定要用命令生成,如果通过在hdfs创建文件夹的方式添加是无效的,原因:创建的文件夹没有包含元数据,
除非:创建文件夹后:
再用命令创建同名分区
或使用修复命令:

  1. msck repair table xxx

这条指令和手滑删除外部表后回复数据是一致的。


动态分区调整

hive默认开启
作用:
解决插入麻烦的问题,对比上面的装载数据-从已有插入,格式。

hive3新的动态分区写法:
不需要修改严格模式

  1. insert into default.dept_partiton partition(deptno) select deptno,dname,loc from dept

hive2旧的动态分区写法:
需要修改为非严格模式(默认是严格模式)

  1. set hive.exec.dynamic.partition.mode=nonstrict
  2. insert into default.dept_partition partition(deptno) select dname,loc from dept

对比静态分区:

  1. insert into default.dept_partition partition(loc="1700") select deptno,dname from dept where loc=1700

区别:不需要写partition,和过滤语句
本质:
动态分区是,表中的分区字段数据是什么,分区就是什么,
而静态分区是写死某个分区。
1)开启动态分区参数设置
(1)开启动态分区功能(默认true,开启)

  1. hive.exec.dynamic.partition=true

(2)设置为非严格模式(动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。)

  1. hive.exec.dynamic.partition.mode=nonstrict

(3)在所有执行MR的节点上,最大一共可以创建多少个动态分区。默认1000(少)

  1. hive.exec.max.dynamic.partitions=1000

(4)在每个执行MR的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错。(少)

  1. hive.exec.max.dynamic.partitions.pernode=100

(5)整个MR Job中,最大可以创建多少个HDFS文件。默认100000(少)

  1. hive.exec.max.created.files=100000

(6)当有空分区生成时,是否抛出异常。一般不需要设置。默认false(少)

  1. hive.error.on.empty.partition=false

2)案例实操
需求:将dept表中的数据按照地区(loc字段),插入到目标表dept_partition的相应分区中。
(1)创建目标分区表
建表和插入同时需要partition语句,否则不能实现分区

  1. hive (default)> create table dept_partition(id int, name string) partitioned
  2. by (location int) row format delimited fields terminated by '\t';

(2)设置动态分区
注意这里:insert 进去的是新表(dept_partition),select 的是旧表(dept),所以字段名可以不一样

  1. set hive.exec.dynamic.partition.mode = nonstrict;
  2. hive (default)> insert into table dept_partition partition(location) select deptno, dname, loc from dept;

(3)查看目标分区表的分区情况

  1. hive (default)> show partitions dept_partition;

思考:目标分区表是如何匹配到分区字段的?

分桶和分桶表

分桶:

就是查询阶段mr的collect阶段调用partition方法 进行分区,sort by 进行排序
image.png
分桶方式:
通过哈希值取余reduce个数进行分桶
分桶设置:
reduce 的个数设置为-1(最好),让job自行决定需要多少个reduce:有多少个reduce就多少个桶
或者将reduce的个数设置大于等于分桶表的桶数:

分桶表:

说明:
最大好处是加快join的速度,详情请看大表join大表(3),
所以一般分桶不直接用,而是当大表join大表的时候会用到。


建表:(桶的个数不能超过可用CPU的核数,不然执行task时会相互抢占资源 )
需要创建两张分桶表
然后分桶表与分桶表之间进行join,
桶的个数需要保持一致

  1. create table stu_buck(id int, name string)
  2. clustered by(id)
  3. into 4 buckets
  4. row format delimited fields terminated by '\t';

查看表结构

  1. hive (default)> desc formatted stu_buck;
  2. Num Buckets:

导入数据到分桶表中

  1. hive (default)> load data local inpath '/opt/module/datas/student.txt' into table stu_buck;

查看创建的分桶表中是否分成4个桶
image.png

然后设置分桶参数才能生效:

image.png

测试:
image.png