天天看點

Hive(二)--分區分桶,内部表外部表

1.簡述

Hive是hadoop生态圈中實作資料倉庫的一項技術。雖然hadoop和hdfs的設計局限了Hive所能勝任的工作,但是hive仍然是目前網際網路中最适合資料蒼鹭的應用技術。不論從“品相還是舉止”,hive都像一個關系型資料庫。使用者對資料庫、表和列這類術語比較熟悉的話,那麼掌握hive的查詢語言HQL也輕而易舉。不過,hive的實作和使用方式與傳統的關系資料庫相比,有很多不同的地方。

2.内部表與外部表

hive将資料表分為内部表和外部表。

内部表

在hive中穿點的普通的表都可以稱為“内部表”。因為hive可以(或多或少)控制其資料的生命周期,内部表對資料擁有所有權。比如我們常見的,通常hive會将内部表資料儲存在有hive.metastore.warehouse.dir所定義的目錄下。

是以,當删除一個内部表時,相應的資料也會被删除。

外部表

内部表不友善共享資料源。例如,當采用如Pig或MapReduce等李樹工具資料處理時,我們将無法讀取内部表的資料,也不能将外部資料直接作為内部表資料源分享給hive。這樣的需求就誕生了外部表。不同于内部表,hive對外部表的資料僅僅擁有使用權,而資料位置可有表管理者任意配置。

Hive(二)--分區分桶,内部表外部表

如圖所示:外部表不需要将資料複制到hive中,一旦關聯資料格式和資料位置,hive就能直接通路外部資料,非常靈活友善,即插即用。

而加載内部表資料時,hive會自動将資料源拷貝到内部。内部表其實通路的是資料副本。

注意:hive架子啊内部表資料後會把源資料删除,很像“剪切/移動”,是以,忘内部表上傳資料時,千萬記得備份資料!

3.分區和分桶分區

對于大型資料處理系統而言,資料分區的功能非常重要的。因為hive通常要對資料進行全盤掃描,才能滿足查詢條件。

以hive管理大型網站的浏覽日志為例。如果日志資料不采用分區實際,那麼就單日網站流量分析這樣的需求而言,hive就必然要通過周遊全量日志來完成查詢。以一年日志為全量,單日查詢的資料使用率将不到1%,這樣的設計基本上将查詢的時間浪費在了資料加載上。分區的優勢在于利用唯獨分割資料。在使用分區次元查詢時,hive隻需要加載資料,極大縮短資料加載時間。

由于HDFS被設計用于存儲大型資料檔案而非海量碎片檔案,理想的分區方案不應該導緻過多的分區檔案,并且每個目錄下的檔案盡量超過HDFS塊大小的若幹倍。按天級時間粒度進行分區就是一個号的分區政策,随時間的推移,分區數量增長均可控。此外常有的分區政策還有地域,語言種類等等。設計分區的時候,還有一個誤區要避免。關于分區次元的選擇,我們應該盡量選擇那些有限且少量的資料集作為分區,例如國家、省份就是一個良好的分區,而城市就可能不适合進行分區。

注意:分區是資料表的一個列名,但是這個列名并不占有表的實際存儲空間。他作為一個虛拟列為存在。

分區提供了一種整理資料和優化查詢的周遊方式。不過,并非所有資料集都可形成合力的分區,特别是在需要合力劃分資料、防止傾斜時。分桶是将資料分解管理的另一種技術。

分桶解決的是資料傾斜的問題。因為痛的資料固定,是以沒有資料波動。桶對于資料抽樣在适合不過,同時也有利于高效的map-side Join。

分桶與分區的關系:

  1. 分區和分桶都可以單獨于表
  2. 分區可以是多級
  3. 分區和分桶可以嵌套使用,但是分區必須在分桶前面

分區表:

  1. 一個表可以擁有一個或多個分區,每個分區以檔案夾的形式單獨存在于表檔案夾的目錄下
  2. 表和列名不區分大小寫
  3. 分區是以字段的形式在表結構中存在,通過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的資料。