Hive支持關(guān)系型數(shù)據(jù)庫的大多數(shù)基本數(shù)據(jù)類型,同時(shí)也支持關(guān)系型數(shù)據(jù)庫中很少出現(xiàn)的3種集合數(shù)據(jù)類型
為什么這么做?
- 考慮因素一:數(shù)據(jù)類型是如何在文本中進(jìn)行表示
- 考慮因素二:文本存儲(chǔ)中為了解決各種性能問題以及其他問題有哪些替代方案
基本數(shù)據(jù)類型
| 數(shù)據(jù)類型 | 長度 | 例子 |
|---|---|---|
| TINYINT | 1byte有符號(hào)整數(shù) | 20 |
| SMALINT | 2byte有符號(hào)整數(shù) | 20 |
| INT | 4byte有符號(hào)整數(shù) | 20 |
| BIGYINT | 8byte有符號(hào)整數(shù) | 20 |
| BOOLEAN | 布爾類型true或false | TRUE |
| FLOAT | 單精度浮點(diǎn) | 3.14159 |
| DOUBLE | 雙精度浮點(diǎn) | 3.14159 |
| STRING | 字符序列,可以指定字符集??梢允褂脝我?hào)或雙引號(hào) | 'string',"string" |
| TIMESTAMP | 整數(shù),浮點(diǎn)或者字符串 | JDBC所兼容的時(shí)間格式 |
| BINARY | 字節(jié)數(shù)組 | 參考后面內(nèi)容 |
所有的這些數(shù)據(jù)類型都是對(duì)Java中的接口實(shí)現(xiàn),因此這些數(shù)據(jù)類型具體行為細(xì)節(jié)和Java中對(duì)應(yīng)的數(shù)據(jù)類型是完全一致的。
如果用戶在查詢中將一個(gè)float和double進(jìn)行比較,Hive會(huì)隱式地將類型轉(zhuǎn)換為兩個(gè)值中較大的類型,也就是把float轉(zhuǎn)為double。
用戶也可以顯示地將一種數(shù)據(jù)類型轉(zhuǎn)為其他一種數(shù)據(jù)類型,如:s = “1”,需要把s轉(zhuǎn)為int則可以用
cast ( s as int)
as 和 int 是關(guān)鍵字,大小寫都可以
集合數(shù)據(jù)類型
| 數(shù)據(jù)類型 | 描述 | 字面語法示例 |
|---|---|---|
| STRUCT | 和C語言中的stuct或者'對(duì)象'類似,都可以通過“點(diǎn)”符號(hào)訪問元素內(nèi)容。例如,如果某個(gè)列的元素類型是STRUCT{fisrt STRING,last STRING},那么第一個(gè)元素可以通過,字段名.first來引用 | struct('John','Doe') |
| MAP | MAP是一組鍵值對(duì)元組集合,使用數(shù)組表示法(例如['key'])可以訪問元素。例如,某個(gè)列的數(shù)據(jù)類型是MAP,其中鍵->值對(duì)是'fisrt' -> 'John'和'last' -> 'Doe',那么可以通過字段名['last']獲取最后一個(gè)元素 | map('fisrt':'John','last':'Doe') |
| ARRAY | 數(shù)組是一組具有相同類型和名稱的變量集合。這些變量稱為數(shù)組元素,每個(gè)數(shù)組元素都有一個(gè)編號(hào),編號(hào)從零開始。例如,數(shù)組值為['John','Doe'],那么第二個(gè)數(shù)組值可以用過數(shù)組名[1]進(jìn)行引用 | Array('John','Doe') |
大多數(shù)的關(guān)系型數(shù)據(jù)庫并不支持這些集合數(shù)據(jù)類型,因?yàn)槭褂盟鼈儠?huì)趨向于破壞標(biāo)準(zhǔn)格式。破壞標(biāo)準(zhǔn)帶來的問題是會(huì)增大數(shù)據(jù)冗余風(fēng)險(xiǎn),進(jìn)而導(dǎo)致不必要的磁盤空間,還有可能造成數(shù)據(jù)不一致,因?yàn)楫?dāng)數(shù)據(jù)發(fā)生改變時(shí)冗余的拷貝數(shù)據(jù)可能無法進(jìn)行相應(yīng)的同步
這里有一個(gè)用于演示如何使用這些數(shù)據(jù)類型的表結(jié)構(gòu)聲明語句,這是一張?zhí)摂M的人力資源應(yīng)用程序的員工表
CREATE TABLE employees(
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING,FLOAT>,
address STRUCT<street:STRING, city:STRING, state:STRING, zip:STRING>
);
文本文件數(shù)據(jù)編碼
常見的文本文件的格式,有以逗號(hào)和制表符分隔的文本文件,也就是所謂的逗號(hào)分隔值(CSV)或制表符分隔值(TSV)。只要用戶需要,Hive是支持這些文件格式的。然而,這兩種格式的文件有一個(gè)共同的缺點(diǎn),那就是:
用戶需要對(duì)文本文件中那些不需要作為分隔符處理的逗號(hào)或者制表符格外小心
也因此,Hive默認(rèn)使用了幾個(gè)控制字符,這些字符很少出現(xiàn)在字段值中。Hive使用術(shù)語field來表示替換分隔符的字符。
Hive中默認(rèn)的記錄和字段分隔符如下表:
| 分隔符 | 描述 |
|---|---|
| \n | 對(duì)于文本來說,每行都是一條記錄,因此換行符可以分割記錄 |
| ^A(Ctrl+A) | 用于分割字段(列)。在CREATE TABLE 語句中可以使用八進(jìn)制編碼\001表示 |
| ^B | 用于分割A(yù)RRAY或者STRUCT中的元素,或用于MAP中鍵值對(duì)之間的分割。在CREATE TABLE語句中可以使用八進(jìn)制編碼\002表示 |
| ^C | 用于MAP中鍵和值之間的分割。在CREATE TABLE語句中可以使用八進(jìn)制編碼\003表示 |
我們看一下employees表中的記錄,其中使用了^A等字符作為字段分割符:

用戶可以不使用這些默認(rèn)分隔符,而指定使用其他分隔符。下面這個(gè)表結(jié)構(gòu)和和之前那個(gè)表是一樣的,不過這里明確制定了分隔符:
CREATE TABLE employees(
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING,FLOAT>,
address STRUCT<street:STRING, city:STRING, state:STRING, zip:STRING>
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\001'
COLLECTION ITEMS TERMINATED BY '\002'
MAP KEYS TERMINATED BY '\003'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
ROW FORMAT DELIMITED這組關(guān)鍵字必須要寫在其他字句(除了 STORED AS ...)之前
讀時(shí)模式
傳統(tǒng)的數(shù)據(jù)庫是寫時(shí)模式(schema on write),即數(shù)據(jù)在寫入數(shù)據(jù)庫時(shí)對(duì)模式進(jìn)行檢查。
Hive對(duì)底層存儲(chǔ)并沒有這樣的控制。Hive不會(huì)在數(shù)據(jù)加載時(shí)進(jìn)行驗(yàn)證,而是在查詢時(shí)進(jìn)行,也就是讀時(shí)模式。
那么如果模式和文件內(nèi)容不匹配將會(huì)怎么樣呢?
Hive對(duì)此做的非常好,因?yàn)槠淇梢宰x取這些數(shù)據(jù)。如果每行記錄匯總字段個(gè)數(shù)少于對(duì)應(yīng)模式中定義的字段個(gè)數(shù)的話,那么用戶將會(huì)看到查詢結(jié)果中有很多null值。如果某些字段是數(shù)值型,但Hive在讀取時(shí)發(fā)現(xiàn)存在非數(shù)值型的字符串值的話,那么對(duì)于那些字段將會(huì)返回null值。除此之外的情況,Hive都極力嘗試盡可能將各種錯(cuò)誤恢復(fù)過來