Hive空值處理
Hive在使用過程中不可避免需要對NULL、’’(空字串)進行判斷和識別。Hive預設情況下底層儲存空值跟其他傳統資料庫有所不同。
1、hive預設儲存空值的規則
(1) 不同資料型別對空值的儲存規則
Int與String型別,NULL底層預設儲存為\N,查詢時顯示為NULL。String型別的資料如果為”“,儲存則是”“,另外往Int型別的欄位插入資料””時,結果還是\N。
(2) 不同資料型別空值的查詢
對於Int型別可以使用is null來判斷空值,對於string型別,條件is null 查出來的是\N的資料,而條件 =”,查詢出來的是”“的資料。
2、修改hive底層儲存和標識空值的方式
建表時可以通過NULL DEFINED AS定義空值的編碼方式,對於已經建立的表,可以通過alter table table_name SET SERDEPROPERTIES(‘serialization.null.format’ = ’ \N’)語句修改hive底層儲存空值的方式。
假設hdfs上有以下5行資料的檔案:
1|NULL|100
2|null|200
3|\N|300
4||400
5|five|500
現使用以下建表語句建立指向該檔案的外部表:
CREATE EXTERNAL TABLE null_test(
c1 int,
c2 string,
c3 int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '|'
STORED AS TEXTFILE
LOCATION '/dianshang/asiainfo/null_test';
(1) 預設情況下hive認為底層資料為\N的資料才是空值,查詢結果用NULL表示,通過is null條件查詢出來的是第三條記錄:
(2) 如果希望hive底層用空字元’’儲存空值,可以在建表時通過NULL DEFINED AS指定或者修改表的屬性值serialization.null.format。
建表時指定空值的編碼方式:
CREATE EXTERNAL TABLE null_test(
c1 int,
c2 string,
c3 int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '|'
STORED AS TEXTFILE
NULL DEFINED AS ''
LOCATION '/dianshang/asiainfo/null_test';
修改表的屬性serialization.null.format改變空值的編碼方式:
alter table null_test SET SERDEPROPERTIES(‘serialization.null.format’ = ”);
此時通過is null查詢條件查出的結果是第4條資料:
同樣可以修改hive底層儲存空值的編碼方式為字串”null”,此時通過is null查詢條件查出的結果是第2條資料:
3、使用sqoop把hive表資料導到oracle時因空值報錯問題。
如果hive底層空值儲存是預設的\N,匯入oracle時會報以下錯誤:
Caused by: java.lang.RuntimeException: Can’t parse input data: ‘\N’,這時可以通過以下方法解決:
(1) 在sqoop匯出語句增加–input-null-string “\\N” –input-null-non-string “\\N” 引數,把\N轉化成空字元’’。
(2) 建表時通過NULL DEFINED AS ”宣告hive底層使用空字元儲存和標識空值。
(3) 通過alter table table_name SET SERDEPROPERTIES(‘serialization.null.format’ = ”) 語句修改hive底層儲存和標識空值為空字元’’,但是修改後需要重跑資料。
綜上所述,需要與外部進行資料互動的表,建表時建議使用NULL DEFINED AS ”宣告hive底層使用空字元’’儲存和標識空值,減少一些不必要的錯誤。在查詢語句中,判斷欄位c為空值的條件建議寫成 c is null or length(c)=0 或者c is null or c=’’。