分区表

默认的 创建一个数据库 对应着一个hdfs 文件夹,创建一个表 对应着一个hdfs文件夹。
而分区表,是在表的文件夹下 再创建多个子文件夹。通过指定的条件,将多个不同属性的数据分割到多个子目录中。主要用来拆分大的数据文件为多个小的数据文件。

使用分区表

  1. 创建一个分区表
1
2
3

create table log(id int ,info string ) partitioned by (date_str string) row format delimited fields terminated by ',';

创建日志表,根据日期进行分区

  1. 插入多个测试数据

1
2
3
4
5
6

insert into log(id,info,date_str) values (1,'sdfdssdfsd','2022_01');
insert into log(id,info,date_str) values (2,'sdfdssdfsd','2022_02');
insert into log(id,info,date_str) values (3,'sdfdssdfsd','2022_03');
insert into log(id,info,date_str) values (4,'sdfdssdfsd','2022_04');

  1. 可以看到在表下的目录创建了多个带着条件的目录存放分别分区的数据

注意:当不指定分区的时候,数据会到默认分区中。 HIVE_DEFAULT_PARTITION

  1. 查询数据
1
2
select * from log;

默认查询数据会从所有分区中加载数据。

1
select * from log where date_str= '2022_01';

带着分区条件属性查询.

尽量将分区条件设置为经常需要查询的条件。

二级分区

分区的字段,可以指定多个,在分区目录下再增加子目录的方式进行管理.

1
2
3
4
5
create table table_partition(
id int, name string
)
partitioned by (day string, hour string)
row format delimited fields terminated by '\t';

天和小时 的2级分区。

分区表的管理

为一个表删除分区

1
2
alter table log drop partition(date_str='2022_01');

删除指定的一个分区。

注意:这个分区内的数据也被删除

为一个表添加分区

1
2
alter table log add partition(date_str='2022_01');

添加分区后将创建一个分区文件夹

查看分区信息

1
2
3

show partitions log;

直接上传到分区目录,如何让hive感知到数据存在

指的是先在hdfs 手动创建好分区目录,而hive的metastore 中还没有此分区信息的情况下

  1. hdfs目录手动创建,分区目录也创建了,数据也导入到分区了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
msck repair table log;


INFO : Compiling command(queryId=hadoop_20220505051050_cce9be9a-090a-48f9-9b0f-48582ed137bb): show partitions log
INFO : Concurrency mode is disabled, not creating a lock manager
INFO : Semantic Analysis Completed (retrial = false)
INFO : Returning Hive schema: Schema(fieldSchemas:[FieldSchema(name:partition, type:string, comment:from deserializer)], properties:null)
INFO : Completed compiling command(queryId=hadoop_20220505051050_cce9be9a-090a-48f9-9b0f-48582ed137bb); Time taken: 0.039 seconds
INFO : Concurrency mode is disabled, not creating a lock manager
INFO : Executing command(queryId=hadoop_20220505051050_cce9be9a-090a-48f9-9b0f-48582ed137bb): show partitions log
INFO : Starting task [Stage-0:DDL] in serial mode
INFO : Completed executing command(queryId=hadoop_20220505051050_cce9be9a-090a-48f9-9b0f-48582ed137bb); Time taken: 0.021 seconds
INFO : OK
INFO : Concurrency mode is disabled, not creating a lock manager

执行此目录修复

  1. 手动执行添加分区命令
1
alter table log add partition(date_str='2022_01');
  1. 在导入数据的时候指定分区
1
2
load data local inpath '/log.log' into table
log partition(day_str='2020_01');

根本就在于在hive感知到分区的存在。

动态分区

上面的分区的字段和对应的值都是固定的,而有时候并不清楚具体的分区值有多少个。期望能够通过数据的值自动完成分区。类似于mysql动态分表的功能。

动态分区配置

动态分区相关的配置

  1. 开启配置

hive.exec.dynamic.partition=true 默认是开启的

  1. 默认是严格模式,严格模式下 必须指定一个分区是静态的分区,所以要使用动态的要设置为非严格模式

hive.exec.dynamic.partition.mode=nonstrict

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

hive.exec.max.dynamic.partitions=1000

  1. 在每个执行MR的节点上,最大可以创建多少个动态分区,需要预估数据的动态分区的数量,不然会报错

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

  1. MR job 中,最多可以创建多少个hdfs文件 默认 100000

hive.exec.max.created.files=100000

  1. 分区为空的时候,是否抛异常,没有分区字段值的时候

hive.error.on.empty.partition=false

以上的这些设置,可以修改 hive-site.xml 永久生效。如果需要改的话。

也可以在命令行中使用set 命令,只针对本次使用生效。

1
2
set hive.exec.dynamic.partition.mode=nonstrict;

动态分区使用

  1. 创建一个员工表,根据部门id 动态分区
    ···
    create table emp( id int, name string)partitioned by (dept_id int) row format delimited fields terminated by ‘,’;
    ···

  2. 向表中插入数据

1
2
3
4
insert into emp(id,name,dept_id) values (1,'名字1',1);
insert into emp(id,name,dept_id) values (2,'名字2',2);
insert into emp(id,name,dept_id) values (3,'名字3',1);

可以看到已经自动帮做了分区。

采用动态分区后,很多种情况会产生mr计算的过程。比静态分区会多很多的计算。