Hive(二)--分割槽分桶,內部表外部表
1.簡述
Hive是hadoop生態圈中實現資料倉庫的一項技術。雖然hadoop和hdfs的設計侷限了Hive所能勝任的工作,但是hive仍然是目前網際網路中最適合資料蒼鷺的應用技術。不論從“品相還是舉止”,hive都像一個關係型資料庫。使用者對資料庫、表和列這類術語比較熟悉的話,那麼掌握hive的查詢語言HQL也輕而易舉。不過,hive的實現和使用方式與傳統的關係資料庫相比,有很多不同的地方。
2.內部表與外部表
hive將資料表分為內部表和外部表。
內部表
在hive中穿點的普通的表都可以稱為“內部表”。因為hive可以(或多或少)控制其資料的生命週期,內部表對資料擁有所有權
所以,當刪除一個內部表時,相應的資料也會被刪除。
外部表
內部表不方便共享資料來源。例如,當採用如Pig或MapReduce等李樹工具資料處理時,我們將無法讀取內部表的資料,也不能將外部資料直接作為內部表資料來源分享給hive。這樣的需求就誕生了外部表。不同於內部表,hive對外部表的資料僅僅擁有使用權,而資料位置可有表管理者任意配置。
如圖所示:外部表不需要將資料複製到hive中,一旦關聯資料格式和資料位置,hive就能直接訪問外部資料,非常靈活方便,即插即用。
而載入內部表資料時,hive會自動將資料來源拷貝到內部。內部表其實訪問的是資料副本。
注意:hive架子啊內部表資料後會把源資料刪除,很像“剪下/移動”,所以,忘內部表上傳資料時,千萬記得備份資料!
3.分割槽和分桶分割槽
對於大型資料處理系統而言,資料分割槽的功能非常重要的。因為hive通常要對資料進行全盤掃描,才能滿足查詢條件。
以hive管理大型網站的瀏覽日誌為例。如果日誌資料不採用分割槽實際,那麼就單日網站流量分析這樣的需求而言,hive就必然要通過遍歷全量日誌來完成查詢。以一年日誌為全量,單日查詢的資料利用率將不到1%,這樣的設計基本上將查詢的時間浪費在了資料載入上。分割槽的優勢在於利用唯獨分割資料。在使用分割槽維度查詢時,hive只需要載入資料,極大縮短資料載入時間。
由於HDFS被設計用於儲存大型資料檔案而非海量碎片檔案,理想的分割槽方案不應該導致過多的分割槽檔案,並且每個目錄下的檔案儘量超過HDFS塊大小的若干倍。按天級時間粒度進行分割槽就是一個號的分割槽策略,隨時間的推移,分割槽數量增長均可控。此外常有的分割槽策略還有地域,語言種類等等。設計分割槽的時候,還有一個誤區要避免。關於分割槽維度的選擇,我們應該儘量選擇那些有限且少量的資料集作為分割槽,例如國家、省份就是一個良好的分割槽,而城市就可能不適合進行分割槽。
注意:分割槽是資料表的一個列名,但是這個列名並不佔有表的實際儲存空間。他作為一個虛擬列為存在。
分割槽提供了一種整理資料和優化查詢的遍歷方式。不過,並非所有資料集都可形成合力的分割槽,特別是在需要合力劃分資料、防止傾斜時。分桶是將資料分解管理的另一種技術。
分桶解決的是資料傾斜的問題。因為痛的資料固定,所以沒有資料波動。桶對於資料抽樣在適合不過,同時也有利於高效的map-side Join。
分桶與分割槽的關係:
- 分割槽和分桶都可以單獨於表
- 分割槽可以是多級
- 分割槽和分桶可以巢狀使用,但是分割槽必須在分桶前面
分割槽表:
- 一個表可以擁有一個或多個分割槽,每個分割槽以資料夾的形式單獨存在於表文件夾的目錄下
- 表和列名不區分大小寫
- 分割槽是以欄位的形式在表結構中存在,通過desc table tablename命令可以檢視到欄位的存在,但是該欄位不存放實際的資料內容,僅僅是分割槽的標識(偽列)
語法:1.建立一個分割槽表
create table t_hive_partition(id int,name string) partitioned by (ds string) row format delimited fields terminated by '\t' stored as textfile
2.將資料新增到時間為xxxx這個分割槽中
load data local inpath '/root/hive_partition.data' overwrite into table t_hive_partition pasrtition(ds = '2018-11-28');
3.從一個分割槽表中查詢資料:
select * from t_hive_partition where ds = '2018-11-28';
4.檢視具體的分割槽情況
show partitions tablename;
分桶分割槽:
對於每一個表或者分割槽,hive可以進一步組織成桶,也就是說是更為細粒度的資料範圍劃分。hive也是針對某一行進行桶的組織。hive採用對列值雜湊,然後除以桶的個數求餘的方式決定該條記錄存放在呢個桶裡面。
比如現在有這樣的資料:我們分四個桶
1 張三
2 李四
3 王五
4 魯班
5 黃忠
桶1裡面有(實際檔名為00000):4魯班
桶2裡面有(實際檔名為00001):1 張三 5黃忠
桶3裡面有(實際檔名為00002):2 李四
桶4裡面有(實際檔名為00003):3 王五
(1)獲得更高的查詢處理效率。桶為表加上了額外的結構,hive在處理有些查詢時能利用這個結構。
(2)使取樣(sampling)更高效。在處理大規模資料集是,在開發和修改查詢的階段,如果能在資料集的一小部分資料上試執行查詢,會帶來很多的方便。
建立帶桶的表:
create table t_bucket(id int,name string) clustered by (id) sorted by (name) into 4 buckets row format delimited fields terminated by '\t' stored as textfile;
對於map端連線的情況,兩個表以相同方式劃分桶。處理左邊表內某個桶的mapper直到右邊表內相匹配的行在對應的桶內。因此,mapper只需要獲取那個桶(這只是右邊表 記憶體儲存資料的一小部分)集可以進行連線。這已優化方法並不一定要求兩個表必須桶的個數相同。兩個表的桶的個數是背書關係也可以。
強制多個reduce進行輸出
要向分桶表中填充成員,需要將hive.enforce.bucketing屬性設定為true。這樣。hive就知道用表定義中宣告的數量來建立桶。然後使用INSERT命令即可。需要注意的是:clustered by和sorted by 不會影響資料匯入,這意味著,使用者必須自己負責資料如何匯入,包扣資料的分桶和排序
往表中插入資料
一般對於分桶表,新增資料採用將另一個表中查詢的結果INSERT到這個分桶表中
對桶中資料進行取樣:
select * from t_bucket tablesample(bucket 1 out of 4 on id);
桶的個數從1開始計數,因此,前面的查詢從4個桶的第一個中獲取所有的使用者。對於一個大規模的、均勻分佈的資料集,這回返回表中四分之一的資料行。我們也可以用其他比例對若干桶進行取樣。
注:tablesample是抽樣語句,語法:TABLESAMPLE(BUCKET x OUT OF y)
y必須是table總bucket數的倍數或者因子。hive根據y的大小,決定抽樣的比例。例如,table總共分了64份,當y=32時,抽取(64/32=)2個bucket的資料,當y=128時,抽取(64/128=)1/2個bucket的資料。x表示從哪個bucket開始抽取。例如,table總bucket數為32,tablesample(bucket 3 out of 16),表示總共抽取(32/16=)2個bucket的資料,分別為第3個bucket和第(3+16=)19個bucket的資料。