Hive的一次踩坑

今天周末,新冠疫情虽然已经逐渐退去,但仍然不能掉以轻心,而且外面还在下雨,正是窝在家看书的好时机,拿出《Hive编程指南》再看一遍,书读百遍,其义自见,这种经典书每看一遍都会有新的收获。当然光看书是不行的,学习必须要有输出,必须要上手实际操作才会印象深刻。

今天按照书上关于分区的部分实际上手操作了一把,发现还是有一些坑在里面的。

本文测试环境:2.1.1-cdh6.3.2, rb3393cf499504df1d2a12d34b4285e5d0c02be11

1. 字段注释乱码

在建表时没有添加COMMENT 字段注释,后面我想通过ALTER TABLE给表字段添加注释时候,发现添加后是??,那么肯定是字符集设置的有问题。打开MySQL,进入Hive的元数据的数据库
修改表注释字段注释在MySQL数据库中对应的字段字符类型。

1
2
3
4
5
alter table COLUMNS_V2 modify column COMMENT varchar(256) character set utf8;

alter table TABLE_PARAMS modify column PARAM_VALUE varchar(4000) character set utf8;

alter table PARTITION_KEYS modify column PKEY_COMMENT varchar(4000) character set utf8;

再次执行ALTER TABLE 修改表注释,然后DESC 表名,字段注释恢复成中文,问题解决。

我安装的是MySQL5.7版本,由于强迫症,我直接修改了MySQL的配置文件
root用户下 vim /etc/my.cnf

1
2
3
4
5
6
7
# 在[mysqld]下添加两行
character_set_server=utf8
collation-server=utf8_general_ci

# 新添加两行
[client]
default-character-set=utf8

最后重新启动MySQL
systemctl restart mysqld
【请勿模仿】而且我还尝试修改了MySQL中的hive库的编码方式为utf8,以及hive库下所有的表的编码方式为utf8,后来才看到网上有文章说有不要改,否则有意外的惊喜。不过我启动集群,暂时一切正常。

2. 外部分区表新增字段后插入数据为NULL

这个坑可以稳定复现

描述:

对于分区表新增字段,向已存在分区中插入数据,新增字段的值全部为NULL。

已存在分区有此问题,新分区并不会产生该问题;

无论是管理表还是外部表都有该问题。

网上搜索答案,在新增字段后,对表进行msck repair table tablename,实际验证此方法无效。

复现过程:

1
2
3
4
5
6
7
8
9
10
11
-- 建表
drop table if exists temp01;
create external table if not exists temp01(id string,name string) partitioned by (sex string)
row format delimited fields terminated by ',' stored as textfile;
-- 添加分区
alter table temp01 add partition(sex='M');
-- 插入数据
insert overwrite table temp01 partition (sex="M")
select "1001","张三";
-- 查询
select * from temp01;

到这里一切正常

1
2
3
4
5
6
7
-- 添加字段
alter table temp01 add columns (birth String comment "生日");
-- 插入数据
insert into temp01 partition (sex="M")
select "1001","刘备","1999-08-09";
-- 查看
select * from temp01;

下面就出问题了,刘备同学的生日实际提示是插入成功了,但这里显示为NULL。

其实问题很简单,分区表的元数据没有更新导致的。

首选的方法是针对该分区单独增加字段。

1
alter table temp01 partition(sex=‘M’) add columns(birth string comment ‘生日’);

另外一种方法是重建该分区,如果是内部表,信息也会被删除。(不建议)

1
2
3
4
5
6
-- 重建分区
alter table temp01 drop partition (sex="M");
alter table temp01 add partition (sex="M");

-- 查看
select * from temp01;

刘备同学的生日已经出现了。

下次一定注意要规避这种情况,直接在添加字段的时候,就要考虑这种情况,可以使用cascade关键字添加字段。

1
alter table temp01 add columns (birth String comment "生日") cascade;

然后回刷数据的时候就不会出现NULL值情况了。

【附】:《Hive编程指南》PDF下载