hive 桶表,以及高效的join方式

2021-09-22 01:46:13 字數 3627 閱讀 3440

前面2種的話都是經常會用到,說下第三種 桶 join

桶(smb)

物理上,每個桶就是表(或分割槽)目錄裡的乙個檔案。

smb的設計是為了解決大表和大表之間的join的。簡單的說下她的思想:大表化成小表,map side join 解決。經典的分而治之的思想。

對乙個表或者乙個分割槽,可以將其劃分為更細的資料塊,桶。在hive中,分桶的方式採取的是:對列的值進行hash除以桶的數量取餘 ;

為什麼要對資料進行分桶:

桶給表加上了額外的結構,在進行某些查詢的時候可以利用這個結構進行高效的查詢;例如: 對於兩個資料表,某兩列都做了桶劃分,可以使用map端的join高效的完成join(桶和桶之間的join,大大減少了join的次數)。

對於資料取樣更加高效

建立桶劃分的表

create table bucketed_user (id int) name string) 

clustered by (id) into 4 buckets; 

用clustered by (id) into 4 buckets 分別指定需要進行分桶的列和需要分桶的數量;

桶中的資料可以根據乙個或多個列另外進行排序。由於這樣對每個桶的連線變成了高效的歸併排序(merge-sort), 因此可以進一步提公升map端連線的效率。以下語法宣告乙個表使其使用排序桶:

create table bucketed_users (id int, name string) 

clustered by (id) sorted by (id asc) into 4 buckets;

使用tips:

兩個表join的時候,小表不足以放到記憶體中,但是又想用map side join這個時候就要用到bucket map join。其方法是兩個join表在join key上都做hash bucket,並且把你打算複製的那個(相對)小表的bucket數設定為大表的倍數。這樣資料就會按照join key做hash bucket。小表依然複製到所有節點,map join的時候,小表的每一組bucket載入成hashtable,與對應的乙個大表bucket做區域性join,這樣每次只需要載入部分hashtable就可以了。

ps:map side join其實也是有侷限性的。他要求從表的資料量較小;從表:left join的右表,right join 的左表。

bucket map join

set hive.optimize.bucketmapjoin = true;

select /*+mapjoin(a) */count(*)

from map_join_test a

join map_join_test b on a.id = b.id;

我們如何保證表中的資料都劃分成桶了呢?把在hive外生成的資料載入到劃分成 桶的表中,當然是可以的。其實讓hive來劃分桶更容易。

對於已存在的表

hive並不檢查資料檔案中的桶是否和表定義中的桶一致(無論是對於桶 的數量或用於劃分桶的列)。如果兩者不匹配,在查詢時可能會碰到錯 誤或未定義的結果。因此,建議讓hive來進行劃分桶的操作。

相關的操作:

要向分桶表中填充成員,需要將 hive.enforce.bucketing 屬性設定為 true。①這 樣,hive 就知道用表定義中宣告的數量來建立桶。然後使用 insert 命令即可。需要注意的是: clustered by和sorted by不會影響資料的匯入,這意味著,使用者必須自己負責資料如何如何匯入,包括資料的分桶和排序。

『set hive.enforce.bucketing = true』 可以自動控制上一輪reduce的數量從而適配bucket的個數,當然,使用者也可以自主設定mapred.reduce.tasks去適配bucket個數,推薦使用』set hive.enforce.bucketing = true』

取樣select * from users 

tablesample(bucket 1 out of 4 on rand()); 

乙個完整的例子:

建立表1   create table student(id int, age int, name string)

2   partitioned by(stat_date string)

3   clustered by(id) sorted by(age) into 2 buckets

4   row format delimited fields terminated by ',';

5    

6   create table student1(id int, age int, name string)

7   partitioned by(stat_date string)

8   clustered by(id) sorted by(age) into 2 buckets

9   row format delimited fields terminated by ',';

設定引數

set hive.enforce.bucketing = true;  

插入資料

insert overwrite table student1 partition(stat_date="20120802")

select id,age,name where stat_date="20120802" sort by age;

疑問: 插入的資料沒有按照age 排序,在桶表中會怎麼表現,還是高效的merge-sort模型嗎?

用load data的方式增加進去的方式,不會按照建表的時候制定的排序字段進行排序,如果是insert 的方式進行資料的插入,是會按照建表的時候制定的字段進行排序的。

注意ps:想要使用兩張桶表進行join的時候,兩個表進行交叉的字段必須是唯一的,不滿足這個條件join出來的結果是錯的。

抽樣hive> select * from student1 tablesample(bucket 1 out of 2 on id);

total mapreduce jobs = 1

launching job 1 out of 1

.......

ok4       18      mac     20120802

2       21      ljz     20120802

6       23      symbian 20120802

time taken: 20.608 seconds

注: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的資料。

join操作的執行原理

hive 修改分桶數 分桶表 Hive中的分桶

對於每乙個表 table 或者分割槽,hive可以進一步組織成桶,也就是說桶是更為細粒度的資料範圍劃分。hive也是針對某一列進行桶的組織。hive採用對列值雜湊,然後除以桶的個數求餘的方式決定該條記錄存放在哪個桶當中。把錶 或者分割槽 組織成桶 bucket 有兩個理由 1 獲得更高的查詢處理效率...

hive 桶表的使用

對於每乙個表或者分割槽來說,可以進一步組織成 桶 其實就是更細粒度的資料範圍。bucket是對指定列進行 hash,然後根據hash值除以桶的個數進行求餘,決定該條記錄存放在哪個桶中。公式 whichbucket hash columnvalue numberofbuckets 公式 要往哪個桶存 ...

hive的分割槽以及分桶

2016年10月26日 09 50 38 閱讀數 3999 1 hive 分割槽表 在hive select查詢中一般會掃瞄整個表內容,會消耗很多時間做沒必要的工作。有時候只需要掃瞄表中關心的一部分資料,因此建表時引入了partition概念。分割槽表指的是在建立表時指定的partition的分割槽...