hive支援很多關系型資料庫都支援的基本資料類型,還支援少有關系型資料庫 的三種集合資料類型。 一個相關的問題是,在文本檔案中,這些資料類型是如何展現的,或者說如何描 述文本的存儲。相較于 大多數資料庫,hive有一個特性,即它在文本中資料的編碼方式上提供了極大的 靈活性。大多資料庫對 于資料在硬碟上的存儲以及資料的生命周期都是完全控制的。為了讓你控制這些 ,hive提供了各種工具 使得對資料的管理和處理變得更加簡單。
基本資料類型
hive支援各種長度的整型、浮點型、布爾型和任意長度的字元串類型。 hive0.8.0添加了時間戳和二 進制類型。
表列出了hive支援的基本資料類型
每一個類型都是在java中執行的,是以資料類型的一些行為細節跟相應的java 類型是一樣的。例如, string是由java string執行,float由 java float執行,等等。
注意,跟其它sql語言一樣,hive不支援最大長度限制的字元數組。關系型數 據庫提供這個特點是為 了性能優化,因為固定長度的記錄更容易查找、掃描等。而對于限制更為松散的 hive,它可能不會包含 資料檔案,并且對檔案格式也相當靈活,hive依賴于用于分割字段的分隔符。此 外,hadoop和hive都強 調優化硬碟的讀寫性能,是以相對而言,列值是否為固定長度就不那麼重要了。
新資料類型timestamp的值可以是整型(從unix紀元時間1970-01-01 00:00:00 開始計算秒數)、單精 度浮點型(從unix紀元時間1970-01-01 00:00:00外加9位毫秒數開始計算秒數) 、字元串(根據jdbc日 期字元串格式約定yyyy-mm-dd hh:mm:ss.fffffffff被解釋)。timestamp被解釋 成utc時間,為此,hive 提供了轉換時區的内置函數,to_utc_timestamp、from_utc_timestamp。
binary類型類似于其它關系型資料庫中的varbinary類型,binary列示存儲在 行中的,而不像blob (binarylargeobject)那樣與行分開存儲。binary的一個用途是,其在一行中包 含任意位元組以防止hive 将其分列成為數值或字元串等。
注意,如果你的目的是忽略每一行的結尾部分,那麼你不需要binary。如果一 個表的表模式定義了3 個列,而資料檔案的每一行包含5個值,hive将會忽略最後兩個值。
假設你現在運作這樣一個查詢:比較單精度浮點列和雙精度浮點列,或比較兩 種不同的整型。hive隐 式的将一個整型轉換成更大的整型,将float轉換成double,轉換任意整型成 double;
假設你現在運作這樣一個查詢:将字元串列翻譯成數值類型。hive可以進行顯 式轉換,例如,s是 string類型,轉換成整型:cast(s as int)。
集合類型
hive支援structs,maps,arrays這三種集合類型。
表列出了hive支援的集合類型
因為使用集合類型會破壞範式,是以大多數關系型資料庫不支援這樣的集合類 型。例如,在傳統的數 據模型中,struct可能會被多個具有外鍵關系的表存儲。破壞範式的實際問題即 造成了資料備援,以緻 于耗費不必要的硬碟空間,且當資料發生改變的時候,将導緻備援資料存在潛在 的資料不一緻。然而, 大資料系統,犧牲範式以獲得更高的計算吞吐量。當處理tb、pb級的資料時,最 快的磁盤磁頭尋道是必 要的,記錄中嵌入的集合可以獲得更短的尋道時間,而尋找外鍵關系需要花費更 多的尋道時間。
注:hive沒有各類“鍵”(指主外鍵等)的概念,可以通過 “索引”實作其功 能。
以下是一個表聲明,描述了如何使用這些類型,假設employee表在虛構的hr應 用中:
create table employees(
name string,
salary float,
subordinates array<string>,
deductions map<string,float>,
address struct<street:string,city:string,state:string,zip:int>);
name是員工們的簡單字元串,float類型對于工資大小足夠了,subordinates 清單是一組字元串值, 表示其下屬(這裡起到的作用是将name作為主鍵,是以subordinates中的每一個 元素都引用到表中的另 一個記錄,沒有下級員工的記錄處為空數組),在傳統模型中,“關系 ”将會從員工到其經 理建立相應的外鍵。
deductions是包含一個鍵值對的映射類型,表示從工資中扣稅的部分。鍵即扣 稅名稱,值即百分比值 或絕對數值。在傳統模型中,則用多個表記錄不同的扣稅類型,這些表的行通常 都包含了扣稅值和一個 指向相應員工記錄的外鍵。
address是員工的家庭位址,用struct表示,其域有“街道”、 “城市”、 “州”、“郵政編碼”,并分别有各自的資料類型。
集合類型遵循java對于泛型的文法規定。例如,map<string,float>表 示映射中的每一個鍵都 是string類型,每一個值都是float類型。array<string>表示數組中的每 一個元素都是string類 型。struct可以是包括各種類型,但是struct中各位置上的資料類型必須與定義 的相同。
資料值的文本檔案編碼
下面通過最簡單的文本檔案來開始探尋hive的檔案格式。毫無疑問,你肯定很 熟悉以逗号(,)或者 制表符作為分隔符的文本檔案,即所謂的csv和tsv,hive支援這些格式,但是此 兩者的缺點在于,不用 于作為分隔符的逗号和制表符可能内嵌在文本中,是以,hive預設使用了其它的 字元(這些字元基本很 少的出現在字元串值當中)。
<a href="http://www.bianceng.cn/database/extra/">檢視本欄目更多精彩内容:http://www.bianceng.cn/database/extra/</a>
表列出了hive預設的分隔符
前面聲明的employee表就是以^a作為行分隔符。類似于emacs的文本編輯器将 會以如下形式表示分隔 符(由于文本的一行超過了這裡一行的長度,是以這裡以空白行作為行的辨別):
john doe^a100000.0^amary smith^btodd jones^afederal taxes^c.2^bstate taxes^c.05^binsurance^c.1^a1 michigan ave.^bchicago^bil^b60600
mary smith^a80000.0^abill king^afederal taxes^c.2bstate taxes^c.05binsurance^c.1^a100 ontario st.^bchicago^bil^b60601
todd jones^a70000.0^afederal taxes^c.15^bstate taxes^c.03^binsurance^c.1^a200 chicago ave.^boak park^bil^b60700
bill king^a60000.0^afederal taxes^c.15^bstate taxes^c.03^binsurance^c.1^a300 obscure dr.^bobscuria^bil^b60100
這樣的文本閱讀起來挺麻煩的,但是可以讓hive去做這個事,接下來從第一行 入手來了解分隔符在文 本檔案中的作用。首先,這種格式有點像如下的json (javascriptobjectnotation)格式:
{
“name”:”john doe”,
“salary”:100000.0,
“subordinates”:["mary smith","todd jones"],
“deductions”:{
“federal taxes”:.2,
“state taxes”: .05,
“insurance”: .1
},
“address”:{
“street”:”1 michigan ave.”,
“city”:”chicago”,
“state”: “il”,
“zip”:60600
}
以下是文本第一行的拆分:
john doe是名字
100000.0是工資
mary smith^btodd jones是下屬mary smith和todd jones
federal taxes^c.2^bstate taxes^c.05^binsurance^c.1是扣稅, “federal taxes”扣 20%,“state taxes”扣5%,“insurance”扣10%
1 michigan ave.^bchicago^bil^b60600是位址
你也可以重寫預設分隔符,在某些應用程式寫資料時使用了不同的分隔給定時 ,重寫分隔符是非常必 要的。以下是相同的表定義,并且添加了預設分隔符的明确指定:
address struct<street:string,city:string,state:string,zip:int>
)
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語句必須出現在其它語句之前,stored as…語句除 外。
字元’\001’是^a的八進制,row format delimited fields terminated by ‘\001’意即hive使用^a分隔字段。
類似的,’\002’是^b的八進制,row format delimitedcollection items terminated by ‘\002’意即hive使用^b分隔集合元素。
最後,’\003’是^c的八進制,row format delimitedmap keys terminated by ‘\003’意即hive使用^c分隔map的鍵和值。
lines terminated by … stored as …語句辨別行分隔符,其不要求前面 加上row format delimited關鍵字。
事實上,hive目前不支援除’\n’以外的任何字元作為行分隔符。
你可以重寫字段、集合以及鍵和值的分隔符,也可以沿用hive的預設分隔符, stored as textfile極 少用到,因為此書中,将預設使用textfile檔案格式。有其他可選檔案格式,這 将在第15章中讨論,其 中相關的如檔案的壓縮将在後續的第11章中讨論。
是以,在你明确聲明所有的這些語句時,最好在大多數情況下使用預設分隔符 ,通常隻需要提供需要 被重寫的部分。這些聲明隻會影響到hive在讀資料檔案時所掃描的内容。除非在 某些特殊限制情況下, 你最好以正确的格式寫入資料。例如,以下是以逗号最為字段分隔符的表定義:
create table some_data(
first float,
second float,
third float,
fields terminated by ‘,';
以制表符作為分隔符時用’\t’,這種強大的定制化特點,使得在使用 hive結合其它建立檔案的 工具以及各種etl(extract,transform,load)處理過程時更加容易和友善。
讀模式
向傳統資料庫中寫資料方式,有加載外資料、寫入查詢的結果,做更新等,數 據庫在資料存儲上有絕 對的控制權,資料庫就像是一個守門員,這也就意味着資料庫的控制是可以以 “資料已寫入 ”的方式執行模式。
hive在基本的存儲上沒有這樣類似的控制權,有很多方式建立、修改甚至毀壞 hive将要查詢的資料數 據,是以,hive隻能以“讀”的方式執行查詢,這就是“讀模式 ”。
這樣一來,如果模式和檔案内容不比對怎麼辦?hive會盡其所能的讀取資料,如果 檔案中的每一行沒有足 夠的字段比對模式的話,hive會将後面的字段補成
null。如果某些字段是數值類型,而hive讀到相應的位置為非數值的字元串,此 時,hive将為這些字段 傳回null,另外很重要的一點是,hive
會盡可能的嘗試從所有錯誤中進行恢複。