分区的种类
静态分区:先创建分区,再加载数据
动态分区:直接加载数据,根据数据动态创建分区
混合分区:分区字段有静态的,也有动态的。
动态分区的玩法:
(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数据到分区表也会自动创建的。