场景描述:
公司埋点项目,数据从接口服务写入kafka集群,再从kafka集群消费写入HDFS文件系统,最后通过Hive进行查询输出。这其中存在一个问题就是:埋点接口中的数据字段是变化,后续会有少量字段添加进来。这导致Hive表结构也需要跟着变化,否则无法通过Hive查询到最新添加字段的数据。
解决办法:
为数据表添加字段,字段必须添加到已有字段的最后面。因为已经存在的数据是按照之前的表结构写入到HDFS文件中的,当添加新字段时为了能兼容前面已经存在的数据。在新增的字段加到分区表后,之前已经存在分区表中的数据会为这些新增的字段赋予默认值NULL。
具体操作:
hive> show databases; //查询当前所有数据库 OK db_hive_test default Time taken: 0.014 seconds, Fetched: 2 row(s) Hive> use default; hive> show create table bp_rec_session; //显示表结构及相关配置信息 OK CREATE TABLE `bp_rec_session`( `appversion` string, …… `cpucs` string) PARTITIONED BY ( `idate` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 'hdfs://x.x.x.x:9000/bp/rec_session' TBLPROPERTIES ( 'last_modified_by'='os', 'last_modified_time'='1519977809', 'parquet.compression'='SNAPPY', 'transient_lastDdlTime'='1519977809') Time taken: 0.024 seconds, Fetched: 65 row(s) hive> alter table bp_rec_session add columns(language string, loginType string); //为分区表添加language和loginType字段 hive> show create table bp_rec_session; //查看修改后的表结构 OK CREATE TABLE `bp_rec_session`( `appversion` string, …… `cpucs` string, `language` string, `logintype` string) PARTITIONED BY ( `idate` string) ROW FORMAT SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat' LOCATION 'hdfs://x.x.x.x:9000/bp/rec_session' TBLPROPERTIES ( 'last_modified_by'='os', 'last_modified_time'='1519977809', 'parquet.compression'='SNAPPY', 'transient_lastDdlTime'='1519977809') hive> select * from bp_rec_session limit 1; //查询表数据,检验对表结构修改后是否还能查询已经存在的数据 OK 7.2 …… Y0MDY2OA=e5d3= 8 NULL NULL 20180105 Time taken: 0.139 seconds, Fetched: 1 row(s)
上述查询结果中的两个"NULL"即为后面添加字段赋予的默认值!
注意(坑):
问题:在hive表中增加字段后,向分区表中写入数据(包含新增字段),查询分区表数据发现新增字段值均为“NULL”!
原因分析:表结构新增字段与创建分区表的顺序不同,导致查询结果不同
1.创建分区在修改表结构之后(能获取新增字段值)
2.创建分区在修改表结构之前(不能获取新增字段值)
对于第二种情况,因为分区表在修改表结构之前已经存在,所有在修改表结构的时候,新增字段并没有被加到分区表中。
而第一种情况在创建分区表的时候,直接使用了最新的表结构,所有分区表中包含所有的字段。
解决办法:
对应第二种情况,在执行完修改表结构语句 alter table table_name add columns(column_name string)后,接着需要执行
语句 alter table table_name partition(partition_name='分区值') add columns(column_name string); 【假设分区表名‘分区值’】