場景描述:
公司埋點項目,數據從接口服務寫入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); 【假設分區表名‘分區值’】