Hive分区的种类 & 分区关联数据的三种方式

分区的种类

静态分区:先创建分区,再加载数据

动态分区:直接加载数据,根据数据动态创建分区

混合分区:分区字段有静态的,也有动态的。

动态分区的玩法:

(1)开启动态分区功能(默认true,开启)
set hive.exec.dynamic.partition=true;

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

(3)在所有执行MR的节点上,最大一共可以创建多少个动态分区。默认1000
set hive.exec.max.dynamic.partitions=1000;

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

创建一个dongtai.txt,添加如下数据:

10703007267488	usa	2014-05-01
10101043505096	usa	2014-05-01
10103043509747	china	2014-05-02
10103043501575	china	2014-05-02
10104043514061	china	2014-05-01

创建普通的表,将数据加载进去:
-- 创建表
create table order_partition
(
    order_no   string,
    type string,
    order_time string
) row format delimited fields terminated by '\t';

-- 加载数据
load data local inpath "/home/hivedata/dongtai.txt" into table order_partition;

接着按照需求,创建动态分区表
create table order_dynamic_partition
(
    order_no   string
) 
partitioned by(type String, `time` String)
row format delimited fields terminated by '\t';

导入数据:效果就是按照type和time 两个字段的数据,动态的创建分区:
一定不要使用load加载数据,要从普通表中查询数据插入到动态表:

insert overwrite table order_dynamic_partition partition (type, `time`)
select order_no, type, order_time  from order_partition;

hive (yhdb)> show partitions order_dynamic_partition;
OK
partition
type=china/time=2014-05-01
type=china/time=2014-05-02
type=usa/time=2014-05-01
Time taken: 0.254 seconds, Fetched: 3 row(s)

思考:order_no, type, order_time 能过换成*

insert overwrite table order_dynamic_partition partition (type, `time`)
select *  from order_partition;

虽然没有报错,但是不建议:
因为动态分区是由规律的:动态分区数据必须是查询数据的后几位。
insert overwrite table order_dynamic_partition partition (type, `time`)
select order_no, type, order_time  from order_partition;

动态分区需要依赖于两个字段的数据,这两个数据必须是最后两个,而且必须数据要照应.
也就是说,不管select 有多少个字段,最后两个字段必须照应,否则有问题!

混合分区的玩法:

--创建一个分区表
create table dy_part2(
id int,
name string
)
partitioned by (year string,month string,day string)
row format delimited fields terminated by ',';
-- 要想往分区表内动态加载数据,必须有普通表

create table temp_part2(
id int,
name string,
year string,
month string,
day string
)
row format delimited fields terminated by ',';

编写一个数据文件:temp_part2.txt 
1,廉德枫,2019,06,25
2,刘浩(小),2019,06,25
3,王鑫,2019,06,25
5,张三,2019,06,26
6,张小三,2019,06,26
7,王小四,2019,06,27
8,夏流,2019,06,27

加载数据到普通表中:
load data local inpath '/home/hivedata/temp_part2.txt' into table temp_part2;

将普通表的数据动态加载到分区表:

- 错误用法:
insert into dy_part2 partition (year='2019',month,day) 
select * from temp_part2;
会报错:
FAILED: SemanticException [Error 10044]: Line 1:12 Cannot insert into target table because column number/types are different 'day': Table insclause-0 has 4 columns, but query has 5 columns.

- 正确用法:
insert into dy_part2 partition (year='2019',month,day) 
select id,name,month,day from temp_part2;

hive (yhdb)> show partitions dy_part2;
OK
partition
year=2019/month=06/day=25
year=2019/month=06/day=26
year=2019/month=06/day=27
Time taken: 0.163 seconds, Fetched: 3 row(s)

分区关联数据的三种方式

1)方式一:上传数据后修复

create table if not exists part5(
id int,
name string,
age int
)
partitioned by (year string,month string,day string)
row format delimited 
fields terminated by ',';
在hdfs上创建文件夹:
hive (yhdb)> dfs -mkdir -p /user/hive/warehouse/yhdb.db/part5/year=2023/month=08/day=28;
上传数据
hive (yhdb)> dfs -put /home/hivedata/user1.txt /user/hive/warehouse/yhdb.db/part5/year=2023/month=08/day=28;

查询数据发现没有数据,原因是partition的元数据没有在mysql中,修复一下:
msck repair table part5;

hive (yhdb)> msck repair table part5;
OK
Partitions not in metastore:    part5:year=2023/month=08/day=28
Repair: Added partition to metastore part5:year=2023/month=08/day=28
Time taken: 0.623 seconds, Fetched: 2 row(s)

通过修复的日志,可以看出,修复操作其实是在part5这个表的元数据中,添加了分区的数据。

再次测试,发现就有数据了!
select * from part5;

2)方式二:上传数据后添加分区

在hdfs上创建文件夹:
hive (yhdb)> dfs -mkdir -p /user/hive/warehouse/yhdb.db/part5/year=2023/month=08/day=27;
上传数据
hive (yhdb)> dfs -put /home/hivedata/user1.txt /user/hive/warehouse/yhdb.db/part5/year=2023/month=08/day=27;
创建一个分区:
alter table part5 add partition(year='2023',month='08',day='27');


先创建一个分区,会不会产生文件夹呢?会!
创建一个分区表,会不会产生文件夹呢?不会!
你也可以先创建分区,在分区的文件夹里面,上传数据!

alter table part5 add partition(year='2023',month='08',day='26');
添加分区之后就有了文件夹:/user/hive/warehouse/yhdb.db/part5/year=2023/month=08/day=26
在这个文件夹里面上传数据:
dfs -put /home/hivedata/user1.txt /user/hive/warehouse/yhdb.db/part5/year=2023/month=08/day=26;

3) 方式三:load数据到分区

load一下数据:
load data local inpath '/home/hivedata/user1.txt' into table
 part5 partition(year='2023',month='08',day='25');

这种方式其实没必要,因为不创建文件夹,load数据到分区表也会自动创建的。

上一篇:如何使用 `global.json` 管理(切换) .NET SDK 版本


下一篇:SIP协议学习总结