講問題之前,先簡單創建一個表:
CREATE TABLE IF NOT EXISTS `my.test_table`( `col1` int COMMENT "第一列", `col2` int COMMENT "第二列" ) COMMENT "測試表" PARTITIONED BY (`pt` int COMMENT "測試分區") ROW FORMAT SERDE "org.apache.hadoop.hive.ql.io.orc.OrcSerde" STORED AS INPUTFORMAT "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat" OUTPUTFORMAT "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat";
初始表有col1,col2兩列,pt分區只是為了對比結果
insert語句列順序
hive不像mysql、oracle這些數據庫一樣在insert的時候可以指定字段,必須在插入的時候插入的是全字段。所以我一直以為可以通過指定插入數據的別名來改變插入字段的順序,好吧,事實證明我是錯的!
我們來簡單作一個設想,假如我們執行以下的sql會發生什么:
insert overwrite table my.test_table partition(pt=1) select 2 as col2, 1 as col1 from my.online_table;
按常規邏輯來說,查詢的時候應該是col1字段都為1,col2字段都為2。但是事實上執行
select col1, col2 from my.test_table;
結果是:
2 1 2 1 2 1 2 1 ....
事實上,hive並不關心你執行insert語句所用的別名,別名代表的字段可以不存在,甚至比別名都可以相同。下面的語句執行也是一樣的效果:
insert overwrite table my.test_table partition(pt=1) select 2 as invalid_col, 1 as invalid_col from my.online_table;
是不是覺得很驚喜。所以,請嚴格保證insert語句中的字段和建表語句中的字段的順序一致!!!
對新增字段插入數據再查詢發現是NULL
hive比較特殊的地方,在於它的表結構和數據其實是分開的。這個會導致,對hive分區表新增字段后,在執行插入分區的動作,會發現其實數據文件中已經有新字段值了,但是在查詢的時候新字段的值還是顯示為null。
例如我執行了下面的方法新增了一列col3:
alter table my.test_table add columns(col3 int comment '第三列')
然后想插入一些數據:
insert overwrite table my.test_table partition(pt=1) select 1 as col1, 2 as col2, 3 as col3 from my.online_table;
結果查詢col1,col2,col3發現結果其實是:
1 2 NULL 1 2 NULL ...1
這是因為你對表結構進行了改變,但是歷史分區的數據卻沒有做改變(新增分區不會出現這個情況)。
為了解決上面的問題,可以采用兩種方式:
- 如果已經執行添加操作,並且沒有帶cascade,可以嘗試下面的方法:
使用replace 恢復表結構,這樣歷史的分區數據都不會消失 alter table industry_db.product replace columns(product_name string comment ‘產品名’);
- 在新增的時候加上cascade關鍵詞
alter table my.test_table add columns(col3 int comment '第三列') cascade
官方文檔描述如下:
The CASCADE|RESTRICT clause is available in Hive 1.1.0. ALTER TABLE ADD|REPLACE COLUMNS with CASCADE command changes the columns of a table's metadata, and cascades the same change to all the partition metadata. RESTRICT is the default, limiting column changes only to table metadata.
如上所述,在1.1.0中表和分區的元數據就是分開處理的,在增加字段的時候添加CASCADE能同時更新表和分區 對於,在添加字段的時候沒有指定的cascade的情況
因為我們在重跑數據的時候,雖然HDFS上的數據更新了,但是我們查詢的時候仍然查詢的是舊的元數據信息(即Mysql中的信息)
注意:對於執行了add column語句之后新生成的分區,是不會有問題的,Hive會自動維護新分區中的元數據。
轉載請注明出處: https://www.cnblogs.com/fnlingnzb-learner/p/13472266.html