事情起因:一个底层表,存储格式为parquet。该表有一列为status,该列的注释需要修改,但是修改的时候误操作把字段类型由int改成了string。hive查询是没有问题的,但是impala同步元数据后,查询历史分区数据时,会报如下错误
问题难点:
由于hive的限制,无法将该列由string改为int
由于规范性原因,新增字段再删掉这一列,可能会对下游有使用该表且为select * from xx 的有影响
该表为ods层表,无法通过上游数据重新导入
历史分区数据还有用,因此不能只保留最新的分区
有一种解决方案是在每一个impala的会话窗口设置参数,使impala可以将元数据和数据映射上,但我试了结果还是一样的。
先说下解决方案:
要创建一个临时表,status列的字段可以是int,也可以是string。看自己的业务需要是什么。出于对下游可能用到该列考虑,还是将该列设为int。
将数据插入到临时表中,对该字段类型做cast强转
删除原表
将临时表的表名改为原表
这个解决方案说到底并不是真的对字段做了操作,而是通过替换表来做的。整体的代码很简单,放一个字段类型为string的。思路都是一样的。
---复现问题ALTER table db.table_name change column status status string;--尝试修复1:创建临时表,status字段为stringCREATE table db.table_name_tmp like db.table_name;insert overwrite table db.table_name_tmp partition(dt)select id, cast(status as string), createtimefrom db.table_name;drop table if exists db.table_name;alter table db.table_name_tmp rename to db.table_name;
问题原因待整理,如果有更好的解决方法,欢迎留言~