hive SQL count時的'\N'


Hive中有種假NULL,它看起來和NULL一摸一樣,但是實際卻不是NULL。

例如如下這個查詢:

hive> desc ljn004;

OK

a       string

Time taken: 0.237 seconds

 

hive> select a from ljn004;

OK

NULL

Time taken: 46.232 seconds

 

看上去好像ljn004的a字段保存了一個 NULL,

但是換一個查詢會發現它和NULL並不一樣:

hive> select a from ljn004 where a is null;

OK

Time taken: 62.56 seconds

 

來看一下實際存儲的是什么:

hive> select * from ljn004;

OK

\N

Time taken: 1.232 seconds

 

hive> select a from ljn004 where a = '\\N';

OK

NULL

Time taken: 72.933 seconds

 

ljn004的a字段實際存儲的是一個'\N',a = '\\N'是因為Hive中'\'是轉義字符,需要對'\'進行一次轉義,所以變成'\\N'。

 

這種假NULL產生的原因實際上源於對表的錯誤操作。在Hive中,空值NULL在底層默認是用'\N'來存儲的,看一個例子:

hive> create table ljn005 (col1 string);

OK

Time taken: 1.258 seconds

1 Rows loaded to ljn005

OK

Time taken: 63.727 seconds

 

hive> insert overwrite table ljn005 select NULL from dual;

 

然后看一下底層的數據存儲:

$ hadoop fs -cat /group/hive/ljn005/attempt_201205041518_256192_m_000000_0

\N

 

可以看到底層數據將NULL存儲成了'\N' 。

這樣的設計存在一個問題是如果實際想存儲'\N',那么實際查詢出來的也是NULL而不是'\N' 。

Hive給出一種並非完美的解決方法就是可以自定義底層用什么字符來表示NULL。

例如我想用字符'a'來表示NULL:

hive> alter table ljn005 SET SERDEPROPERTIES('serialization.null.format' = 'a');

OK

Time taken: 0.175 seconds

 

hive> insert overwrite table ljn005 select NULL from dual;

1 Rows loaded to ljn005

OK

Time taken: 62.66 seconds

 

再看一下底層的存儲:

$ hadoop fs -cat /group/hive/ljn005/attempt_201205041518_256764_m_000000_0

a

 

這時候底層的存儲就變成了'a' ,今后插入到這張表中的'a'查詢出來就變成了NULL而不是'a' 。

 

其實上面說的這個假NULL出現的原因就是在默認情況下(即用'\N'表示NULL),插入了NULL值,然后又用SET SERDEPROPERTIES語句修改了存儲NULL的字符串。這時候表的屬性修改了,但是底層存儲的文件並沒有修改。而'\N'顯示為NULL在Hive中又是一個特例,於是就出現了這個假NULL,在開發過程中一定要注意!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM