hive元数据
在使用 Alter语句修改 Hive 分区表结构的时候,会出现已存在的分区结构没有被修改的情况。比如说,新增了一个字段,但是向原有分区插入新增字段数据之后,查询却发现数据为 NULL,或者修改了一个字段类型,查询原有分区的时候发现数据没有被正确识别。
之所以会出现这种情况,是因为 Hive对应分区表表结构的修改,默认采用了限制模式。限制模式下,修改分区表结构的时候,只会对修改后新增的分区有效,修改表结构前已存在的分区不受影响。对应的,Hive也提供了级联修改的命令,在Alter 语句后添加 cascade参数,就可以连同过去存在的分区一起修改表结构(注意:Hive在0.15 版本之后才提供此参数)。
不过,在实际使用过程中,当历史分区数据过多的时候(比如千个以上),使用 cascade参数修改表结构,会出现操作超时的情况;或者是忘记使用 cascade参数的情况。这些情况下,我们就需要通过直接修改 Hive 元数据的方式来修改 Hive表结构。
使用修改元数据的方式修改分区表结构分两步。首先是使用 Alter语句修改表结构。然后登陆到Hive 的元数据库,执行 SQL语句修改已存在分区对应的表结构信息。以 MySQL 元数据库为例,需要执行以下语句(将表名、库名替换成需要修改的表的库名和表名):
UPDATE TBLS T1,DBST2,SDS T3,PARTITIONS T4,SDS T5
SET T5.CD_ID = T3.CD_ID
WHERE T2.NAME = '库名'
AND T1.TBL_NAME = '表名'
AND T1.DB_ID = T2.DB_ID
AND T1.SD_ID = T3.SD_ID
AND T1.TBL_ID =T4.TBL_ID
ANDT4.SD_ID = T5.SD_ID
;
执行上面语句以后,就会将原有分区的表结构信息同步成最新的表结构。
以下是涉及到的 Hive元数据库的表。一个有五张,库/表/存储/字段/分区。
DBS,用于存储数据库信息
字段名 |
说明 |
示例 |
DB_ID |
数据库ID |
1 |
DESC |
描述 |
Default Hive database |
DB_LOCATION_URI |
HDFS路径信息 |
hdfs://namenode:9000/user/hive/warehouse |
NAME |
名称 |
default |
OWNER_NAME |
所有者名称 |
public |
OWNER_TYPE |
所有者类型 |
ROLE |
TBLS,用于存储表基本信息
字段名 |
说明 |
示例 |
TBL_ID |
表ID |
1 |
CREATE_TIME |
创建时间 |
1469592205 |
DB_ID |
所在数据库ID |
1 |
LAST_ACCESS_TIME |
最后访问时间 |
0 |
OWNER |
所有者 |
hadoop |
RETENTION |
保留字段 |
0 |
SD_ID |
存储ID |
1,对应 SDS的 SD_ID |
TBL_NAME |
表名 |
l_test1 |
TBL_TYPE |
表类型 |
常见的有MANAGED_TABLE、EXTERNAL_TABLE |
VIEW_EXPANDED_TEXT |
|
|
VIEW_ORIGINAL_TEXT |
|
|
SDS,文件存储的基本信息
字段名 |
说明 |
示例 |
SD_ID |
存储ID |
1 |
CD_ID |
字段信息ID |
1,对应COLUMNS_V2 的CD_ID |
INPUT_FORMAT |
文件输入格式 |
org.apache.hadoop.mapred.TextInputFormat |
IS_COMPRESSED |
是否压缩 |
0 |
IS_STOREDASSUBDIRECTORIES |
是否以子目录存储 |
0 |
LOCATION |
HDFS路径信息 |
hdfs://namenode:9000/user/hive/warehouse/l_test1 |
NUM_BUCKETS |
分桶数量 |
-1 |
OUTPUT_FORMAT |
文件输出格式 |
org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat |
SERDE_ID |
序列化类ID |
1 |
COLUMNS_V2,字段基本信息
字段名 |
说明 |
示例 |
CD_ID |
字段信息ID |
1 |
COMMENT |
注释信息 |
测试字段1 |
COLUMN_NAME |
列名 |
val1 |
TYPE_NAME |
字段类型 |
string |
INTEGER_IDX |
字段顺序 |
1 |
PARTITIONS,存储各个分区的基本信息
字段名 |
说明 |
示例 |
PART_ID |
分区ID |
1 |
CREATE_TIME |
创建时间 |
|
LAST_ACCESS_TIME |
最后访问时间 |
|
PART_NAME |
分区名称 |
2016-12-19 |
SD_ID |
存储ID |
1 |
TBL_ID |
表ID |
1 |
他们之间的关系如下:
Hive分区表的分区字段信息是单独存储的,上面的语句,就是将 SDS 中存储的原有分区的 CD_ID更新成表最新的 CD_ID。