hive 正常用 hql 查询的时候除了数据倾斜之外都很正常,但是一旦有别的操作就会出现各种各样的问题。有时候出问题了好好想想或许能想明白,有时候怎么想也想不明白就要动手去尝试。
hive 分区表增加列
最近 hive 的一张分区表需要增加两列,第一天直接在那张表上增加了两列,然后把数据插入进去了,结果悲剧了。
1
ALTER TABLE table ADD COLUMNS(col1 string, col2 string);
修改完表结构重新跑完数据之后,新增的两列怎么查都是 NULL 值,查不到真实应该存在的数据,重新跑了好多遍最后都开始怀疑人生了,为什么数据插入不进去呢?后来心一横,我就直接把新增的字段分别赋值成 1
和 2
,不相信还插入不进去。结果再查这张表新增的列的时候还真的还是 NULL,我不信邪直接查看 HDFS 上的文件,结果 HDFS 上文件一点没毛病,该有的值都有,我现在就开始深度的怀疑人生了。
等到第二天,有新的数据进来了,所以又新建了一个分区(数据是按照时间来分区的),我索性就在新的分区上又尝试了一遍,结果新建的那两列的数据完完整整的显示出来了,顿时感觉前途一片光明,虽然数据出来了,但是还是不知道是啥原因,于是乎接着又往下查了查。
最终查明了原因,是这样子的:修改表结构之后,hive 元数据库中表 COLUMNS_V2
的 CD_ID
会随之改变(确切的说是原来的 CD_ID
对应的列信息不变只是失效了,然后新建这个表的所有列信息,增加一个 CD_ID
),然而 SDS
记录表分区中的 CD_ID
不会随之改变。查询历史的分区的数据还是用老的 CD_ID
,查询新的分区的数据会用到新的 CD_ID
,所以新增字段后新增的分区会显示新增的字段,而老的分区只会识别之前的 CD_ID
,无论是否有数据都是读不出来的。
如果需要将历史的数据也要增加新的字段,需要更新分区信息:
1
update SDS set CD_ID = NEW_CD_ID WHERE CD_ID = OLD_CD_ID;
另附上 hive 元数据表信息的 sql,这样查询出来的结果是最新的结果(当前在用的)。分区表的每一个分区信息在SDS
表中都会记录,会记录对应表的CD_ID
和 HDFS 储存的位置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SELECT
DBS.DB_ID,
DBS.`NAME`,
TBLS.TBL_ID,
TBLS.TBL_NAME,
COL.CD_ID,
COL.COLUMN_NAME,
COL.`COMMENT`,
COL.INTEGER_IDX,
COL.CD_ID,
COL.TYPE_NAME
FROM
COLUMNS_V2 COL
LEFT JOIN CDS ON COL.CD_ID = CDS.CD_ID
LEFT JOIN SDS ON CDS.CD_ID = SDS.CD_ID
LEFT JOIN TBLS ON SDS.SD_ID = TBLS.SD_ID
LEFT JOIN DBS ON TBLS.DB_ID = DBS.DB_ID
WHERE
DBS. NAME = 'default'
AND TBLS.TBL_NAME = 'table'
解决 hiveserver2 缓存的问题
最简单的方法当然是重启一下服务,什么缓存都不存在了。不过有时候用到这个服务的程序太多了,不能随随便便重启,所以要手动进去“清除”一下缓存然后再恢复到以前的样子。
1
2
3
4
5
beeline -u jdbc:hive2://localhost:10010 -n username -p password
set datanucleus.cache.level2.type=none;
set datanucleus.cache.level2.type=SOFT;