由于之前的工作中就算是分区表中插入字段,也是只对当前数据负责,不需要管历史数据,所以没考虑过如果加字段之后,对历史分区如何插入数据的问题,直到一次面试,面试官问了这个问题,我决定用博客的形式记录下来,下面是加字段加不加cascade关键字的区别
-- 内容准备
test_partition.txt -- 历史分区没有新增字段
1 zhangsan 1000 20210101
2 lisi 500 20210101
3 wangwu 6000 20210101
4 zhaoliu 4600 20210101
test_partition2.txt -- 新增字段后插入新的分区
5 hanli 8000 mail 20210102
6 wusun 3500 femail 20210102
7 yezi 9000 mail 20210102
8 xaingjiao 7600 femail 20210102
test_partition3.txt -- 历史分区数据加上新的字段
1 zhangsan 1000 mail 20210101
2 lisi 500 mail 20210101
3 wangwu 6000 femail 20210101
4 zhaoliu 4600 mail 20210101
-- 创建表 分区表
create table test(
id int,
name string,
salary string
)
partitioned by (bbq_d_p string)
row format delimited fields terminated by ' ';
-- 第一次加载数据
load data local inpath '/usr/local/temp/test_partition.txt' overwrite into table test partition(bbq_d_p='20210101');
select * from test; -
==>
test.id test.name test.salary test.bbq_d_p
1 zhangsan 1000 20210101
2 lisi 500 20210101
3 wangwu 6000 20210101
4 zhaoliu 4600 20210101
alter table test add columns(sex string); -- 新增字段,没有使用cascade关键字,历史分区表中实际上没有插入这个字段,新增字段设置Null
select * from test;
==>
test.id test.name test.salary test.sex test.bbq_d_p
1 zhangsan 1000 NULL 20210101
2 lisi 500 NULL 20210101
3 wangwu 6000 NULL 20210101
4 zhaoliu 4600 NULL 20210101
load data local inpath '/usr/local/temp/test_partition2.txt' overwrite into table test partition(bbq_d_p='20210102');
select * from test; --发现新建的分区新增的字段成功写入了,那我们试一试历史分区的新增字段数据是否能写入成功
==> 新增字段后,创建的分区是可以写入新增字段数据的
test.id test.name test.salary test.sex test.bbq_d_p
1 zhangsan 1000 NULL 20210101
2 lisi 500 NULL 20210101
3 wangwu 6000 NULL 20210101
4 zhaoliu 4600 NULL 20210101
5 hanli 8000 mail 20210102
6 wusun 3500 femail 20210102
7 yezi 9000 mail 20210102
8 xaingjiao 7600 femail 20210102
-- 写入历史分区,看效果
load data local inpath '/usr/local/temp/test_partition3.txt' overwrite into table test partition(bbq_d_p='20210101');
select * from test; -- 在历史分区中新增的字段都会置为null 没有成功插入数据
==>
test.id test.name test.salary test.sex test.bbq_d_p
1 zhangsan 1000 NULL 20210101
2 lisi 500 NULL 20210101
3 wangwu 6000 NULL 20210101
4 zhaoliu 4600 NULL 20210101
5 hanli 8000 mail 20210102
6 wusun 3500 femail 20210102
7 yezi 9000 mail 20210102
8 xaingjiao 7600 femail 20210102
-- 重头再来
drop table if exists test;
create table test(
id int,
name string,
salary string
)
partitioned by (bbq_d_p string)
row format delimited fields terminated by ' ';
-- 第一次加载数据
load data local inpath '/usr/local/temp/test_partition.txt' overwrite into table test partition(bbq_d_p='20210101');
alter table test add columns(sex string) cascade;
-- 重新载入历史分区数据
load data local inpath '/usr/local/temp/test_partition3.txt' overwrite into table test partition(bbq_d_p='20210101');
select * from test; -- 发现这样历史分区中新插入的字段也成功写入了数据
==>
test.id test.name test.salary test.sex test.bbq_d_p
1 zhangsan 1000 mail 20210101
2 lisi 500 mail 20210101
3 wangwu 6000 femail 20210101
4 zhaoliu 4600 mail 20210101
cascade关键字作用:强制刷新表和所有分区的元数据信息(包括历史数据分区的)
总结起来,想让所有分区都能重新插入数据
①增加字段时使用cascade关键字,强制刷新表和分区元数据信息
②不使用cascade关键字增加字段后,使用下面的语句刷新指定分区的元数据信息,该历史分区就可以重新插入数据
alter table tableName add columns(columnName columnType);
alter table tableName partition(partitionColumnName='partitionValue') add columns(columnName columnType);
③有些hive版本比较低不支持cascade,则需要备份数据,删除该分区后再insert overwrite。