天天看点

Hive分区表新增字段值为NULL背景原因方案

背景

对于HIVE分区表通过add column添加字段,向已存在分区中插入数据,结果新增字段的值全部为null。 已存在分区会产生该问题,新分区不会产生该问题。

原因

实际上数据是插入成功的。HDFS上的数据更新了,但是我们查询的时候仍然查询的是旧的元数据信息(即Mysql中的信息)

官方解释如下:

Change Column Name/Type/Position/Comment

ALTER TABLE table_name [PARTITION partition_spec] CHANGE [COLUMN] col_old_name col_new_name column_type
           

[COMMENT col_comment] [FIRST|AFTER column_name] [CASCADE|RESTRICT];

This command will allow users to change a column’s name, data type, comment, or position, or an arbitrary combination of them. The PARTITION clause is available in Hive 0.14.0 and later; see Upgrading Pre-Hive 0.13.0 Decimal Columns for usage. A patch for Hive 0.13 is also available (see HIVE-7971).

The CASCADE|RESTRICT clause is available in Hive 1.1.0. ALTER TABLE CHANGE COLUMN with CASCADE command changes the columns of a table’s metadata, and cascades the same change to all the partition metadata. RESTRICT is the default, limiting column change only to table metadata.

ALTER TABLE CHANGE COLUMN CASCADE clause will override the table partition’s column metadata regardless of the table or partition’s protection mode. Use with discretion.

The column change command will only modify Hive’s metadata, and will not modify data. Users should make sure the actual data layout of the table/partition conforms with the metadata definition.

也就是说不仅仅是新增字段,修改字段也会出现类型问题。

方案

方案一

DDL语句最后添加CASCADE,会强制刷新元数据信息。

方案二

具体分区需要add column操作

例如,执行下面语句后,查分区数据新增字段值为null

alter table TABLENAME add columns(c1 string);  
           

需再执行

alter table TABLENAME partition(PAR='X') add columns(c1 string);
           

方案三

备份以前表,新建表,然后把备份数据导入回新建表。

方案四(未亲自测试)

删除旧分区,然后重新添加新分区或修复表结构。

修复表结构语句如下:

msck repair table table_name;
           

方案五(未亲自测试)

手动更新元数据,在元数据库里执行如下语句

--查找表对应的CD_ID
select CD_ID from SDS where LOCATION='hdfs://ods.db/tablename';   
           
--查找表总共有哪些分区
SELECT * FROM SDS WHERE LOCATION LIKE 'hdfs://bidc/ods.db/tablname/pt=%';   
           
--更新全部分区,如果要指定更新的分区,把%改为确切的分区值即可
UPDATE SDS SET CD_ID=(查询1中的CD_ID的值)   WHERE LOCATION LIKE 'hdfs://bidc/ods.db/tablename/pt=%';