天天看點

hive資料類型和檔案格式

hive支援很多關系型資料庫都支援的基本資料類型,還支援少有關系型資料庫 的三種集合資料類型。 一個相關的問題是,在文本檔案中,這些資料類型是如何展現的,或者說如何描 述文本的存儲。相較于 大多數資料庫,hive有一個特性,即它在文本中資料的編碼方式上提供了極大的 靈活性。大多資料庫對 于資料在硬碟上的存儲以及資料的生命周期都是完全控制的。為了讓你控制這些 ,hive提供了各種工具 使得對資料的管理和處理變得更加簡單。

基本資料類型

hive支援各種長度的整型、浮點型、布爾型和任意長度的字元串類型。 hive0.8.0添加了時間戳和二 進制類型。

表列出了hive支援的基本資料類型

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支援的集合類型

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預設的分隔符

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&lt;street:string,city:string,state:string,zip:int&gt;

)

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

會盡可能的嘗試從所有錯誤中進行恢複。