hive分割槽與分桶

2021-06-22 05:29:17 字數 4820 閱讀 7553

在hive select查詢中一般會掃瞄整個表內容,會消耗很多時間做沒必要的工作。有時候只需要掃瞄表中關心的一部分資料,因此建表時引入了partition概念。分割槽表指的是在建立表時指定的partition的分割槽空間。

hive可以對資料按照某列或者某些列進行分割槽管理,所謂分割槽我們可以拿下面的例子進行解釋。

當前網際網路應用每天都要儲存大量的日誌檔案,幾g、幾十g甚至更大都是有可能。儲存日誌,其中必然有個屬性是日誌產生的日期。在產生分割槽時,就可以按照日誌產生的日期列進行劃分。把每一天的日誌當作乙個分割槽。

將資料組織成分區,主要可以提高資料的查詢速度。至於使用者儲存的每一條記錄到底放到哪個分割槽,由使用者決定。即使用者在載入資料的時候必須顯示的指定該部分資料放到哪個分割槽。

1.1 實現細節

1、乙個表可以擁有乙個或者多個分割槽,每個分割槽以資料夾的形式單獨存在表資料夾的目錄下。

2、表和列名不區分大小寫。

3、分割槽是以字段的形式在表結構中存在,通過describe table命令可以檢視到字段存在,

但是該字段不存放實際的資料內容,僅僅是分割槽的表示(偽列)

。1.2 語法

1. 建立乙個分割槽表,以 ds 為分割槽列:

create table invites (id int, name string) partitioned by (ds string) row format delimited fields terminated by 't' stored as textfile;

2. 將資料新增到時間為 2013-08-16 這個分割槽中:

load data local inpath '/home/hadoop/desktop/data.txt' overwrite into table invites partition (ds='2013-08-16');

3. 將資料新增到時間為 2013-08-20 這個分割槽中:

load data local inpath '/home/hadoop/desktop/data.txt' overwrite into table invites partition (ds='2013-08-20');

4. 從乙個分割槽中查詢資料:

select * from invites where ds ='2013-08-12';

5.  往乙個分割槽表的某乙個分割槽中新增資料:

insert overwrite table invites partition (ds='2013-08-12') select id,max(name) from test group by id;

可以檢視分割槽的具體情況,使用命令:

hadoop fs -ls /home/hadoop.hive/warehouse/invites

或者:show partitions tablename;

對於每乙個表(table)或者分割槽,

hive可以進一步組織成桶,也就是說桶是更為細粒度的資料範圍劃分。hive也是

針對某一列進行桶的組織。hive採用對列值雜湊,然後除以桶的個數求餘的方式決定該條記錄存放在哪個桶當中。

把錶(或者分割槽)組織成桶(bucket)有兩個理由:

(1)獲得更高的查詢處理效率。桶為表加上了額外的結構,hive 在處理有些查詢時能利用這個結構。具體而言,連線兩個在(包含連線列的

)相同列上劃分了桶的表,可以使用 map 端連線 (map-side join)高效的實現。

比如join操作。對於join操作兩個表有乙個相同的列,如果對這兩個表都進行了桶操作。那麼將儲存相同列值的桶進行join操作就可以,可以大大較少join的資料量。

(2)使取樣(sampling)更高效。在處理大規模資料集時,在開發和修改查詢的階段,如果能在資料集的一小部分資料上試執行查詢,會帶來很多方便。

1. 建立帶桶的 table :

create table bucketed_user(id int,name string) clustered by (id) sorted by(name) into 4 buckets row format delimited fields terminated by '\t' stored as textfile;

首先,我們來看如何告訴hive—個表應該被劃分成桶。我們使用clustered by 子句來指定劃分桶所用的列和要劃分的桶的個數:

create table bucketed_user (id int) name string)

clustered by (id) into 4 buckets;

在這裡,我們使用使用者id來確定如何劃分桶(hive使用對值進行雜湊並將結果除 以桶的個數取餘數。這樣,任何一桶裡都會有乙個隨機的使用者集合(ps:其實也能說是隨機,不是嗎?)。

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

create table bucketed_users (id int, name string)

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

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

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

有乙個沒有劃分桶的使用者表:

hive> select * from users;

0    nat

2    doe

b    kay

4    ann

2. 強制多個 reduce 進行輸出:

要向分桶表中填充成員,需要將 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' 

3. 往表中插入資料:

insert overwrite table bucketed_users select * from users;

物理上,每個桶就是表(或分割槽)目錄裡的乙個檔案。它的檔名並不重要,但是桶 n 是按照字典序排列的第 n 個檔案。事實上,桶對應於 mapreduce 的輸出檔案分割槽:乙個作業產生的桶(輸出檔案)和reduce任務個數相同。我們可以通過檢視剛才 建立的bucketd_users表的布局來了解這一情況。執行如下命令: 

4. 檢視表的結構:

hive> dfs -ls /user/hive/warehouse/bucketed_users;

將顯示有4個新建的檔案。檔名如下(檔名包含時間戳,由hive產生,因此 每次執行都會改變):

attempt_201005221636_0016_r_000000_0

attempt_201005221636_0016_r-000001_0

attempt_201005221636_0016_r_000002_0

attempt_201005221636_0016_r_000003_0

第乙個桶裡包括使用者ido和4,因為乙個int的雜湊值就是這個整數本身,在這裡 除以桶數(4)以後的餘數:②

5. 讀取資料,看每乙個檔案的資料:

hive> dfs -cat /user/hive/warehouse/bucketed_users/*0_0;

0 nat

4 ann

用tablesample子句對錶進行取樣,我們可以獲得相同的結果。這個子句會將 查詢限定在表的一部分桶內,而不是使用整個表:

6. 對桶中的資料進行取樣:

hive> select * from bucketed_users

>    tablesample(bucket 1 out of 4 on id);

0 nat

4 ann

桶的個數從1開始計數。因此,前面的查詢從4個桶的第乙個中獲取所有的使用者。 對於乙個大規模的、均勻分布的資料集,這會返回表中約四分之一的資料行。我們 也可以用其他比例對若干個桶進行取樣(因為取樣並不是乙個精確的操作,因此這個 比例不一定要是桶數的整數倍)。例如,下面的查詢返回一半的桶:

7. 查詢一半返回的桶數:

hive> select * from bucketed_users

>    tablesample(bucket 1 out of 2 on id);

0 nat

4 ann

2 joe

因為查詢只需要讀取和tablesample子句匹配的桶,所以取樣分桶表是非常高效

的操作。如果使用rand()函式對沒有劃分成桶的表進行取樣,即使只需要讀取很

小一部分樣本,也要掃瞄整個輸入資料集:

hive〉 select * from users

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

2 doe

①從hive 0.6.0開始,對以前的版本,必須把mapred.reduce .tasks設為表中要填 充的桶的個數。如果桶是排序的,還需要把hive.enforce.sorting設為true。

②顯式原始檔案時,因為分隔字元是乙個不能列印的控制字元,因此欄位都擠在一起。

Hive分割槽表與分桶

在hive select查詢中,一般會掃瞄整個表內容,會消耗很多時間做沒必要的工作。分割槽表指的是在建立表時,指定partition的分割槽空間。分割槽語法 分割槽表操作增加分割槽 刪除分割槽 alter table employees drop ifexists partition country...

hive的分桶,和分割槽

開啟分桶模式 set hive.enforce.bucketing true 制定reduce個數是4 set mapreduce.job.reduces 4 建立乙個分桶表 create table stu buck sno int,sname string,string,sage int,sde...

hive的分割槽以及分桶

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