溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Hive中分區(qū)、桶的示例分析

發(fā)布時(shí)間:2021-12-16 14:15:24 來源:億速云 閱讀:157 作者:小新 欄目:云計(jì)算

這篇文章給大家分享的是有關(guān)Hive中分區(qū)、桶的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

1、Hive 分區(qū)表

在Hive Select查詢中一般會(huì)掃描整個(gè)表內(nèi)容,會(huì)消耗很多時(shí)間做沒必要的工作。有時(shí)候只需要掃描表中關(guān)心的一部分?jǐn)?shù)據(jù),因此建表時(shí)引入了partition概念。分區(qū)表指的是在創(chuàng)建表時(shí)指定的partition的分區(qū)空間。

Hive可以對(duì)數(shù)據(jù)按照某列或者某些列進(jìn)行分區(qū)管理,所謂分區(qū)我們可以拿下面的例子進(jìn)行解釋。
當(dāng)前互聯(lián)網(wǎng)應(yīng)用每天都要存儲(chǔ)大量的日志文件,幾G、幾十G甚至更大都是有可能。存儲(chǔ)日志,其中必然有個(gè)屬性是日志產(chǎn)生的日期。在產(chǎn)生分區(qū)時(shí),就可以按照日志產(chǎn)生的日期列進(jìn)行劃分。把每一天的日志當(dāng)作一個(gè)分區(qū)。
將數(shù)據(jù)組織成分區(qū),主要可以提高數(shù)據(jù)的查詢速度。至于用戶存儲(chǔ)的每一條記錄到底放到哪個(gè)分區(qū),由用戶決定。即用戶在加載數(shù)據(jù)的時(shí)候必須顯示的指定該部分?jǐn)?shù)據(jù)放到哪個(gè)分區(qū)。
 

1.1 實(shí)現(xiàn)細(xì)節(jié)

1、一個(gè)表可以擁有一個(gè)或者多個(gè)分區(qū),每個(gè)分區(qū)以文件夾的形式單獨(dú)存在表文件夾的目錄下。
2、表和列名不區(qū)分大小寫。
3、分區(qū)是以字段的形式在表結(jié)構(gòu)中存在,通過describe table命令可以查看到字段存在, 但是該字段不存放實(shí)際的數(shù)據(jù)內(nèi)容,僅僅是分區(qū)的表示(偽列) 。
 

1.2 語法

1. 創(chuàng)建一個(gè)分區(qū)表,以 ds 為分區(qū)列:
create table invites (id int, name string) partitioned by (ds string) row format delimited fields terminated by 't' stored as textfile;
2. 將數(shù)據(jù)添加到時(shí)間為 2013-08-16 這個(gè)分區(qū)中:
load data local inpath '/home/hadoop/Desktop/data.txt' overwrite into table invites partition (ds='2013-08-16');
3. 將數(shù)據(jù)添加到時(shí)間為 2013-08-20 這個(gè)分區(qū)中:
load data local inpath '/home/hadoop/Desktop/data.txt' overwrite into table invites partition (ds='2013-08-20');
4. 從一個(gè)分區(qū)中查詢數(shù)據(jù):
select * from invites where ds ='2013-08-12';
5.  往一個(gè)分區(qū)表的某一個(gè)分區(qū)中添加數(shù)據(jù):
insert overwrite table invites partition (ds='2013-08-12') select id,max(name) from test group by id;
可以查看分區(qū)的具體情況,使用命令:
hadoop fs -ls /home/hadoop.hive/warehouse/invites
或者:
show partitions tablename;

2、Hive 桶

對(duì)于每一個(gè)表(table)或者分區(qū), Hive可以進(jìn)一步組織成桶,也就是說桶是更為細(xì)粒度的數(shù)據(jù)范圍劃分。Hive也是 針對(duì)某一列進(jìn)行桶的組織。Hive采用對(duì)列值哈希,然后除以桶的個(gè)數(shù)求余的方式?jīng)Q定該條記錄存放在哪個(gè)桶當(dāng)中。

把表(或者分區(qū))組織成桶(Bucket)有兩個(gè)理由:

(1)獲得更高的查詢處理效率。桶為表加上了額外的結(jié)構(gòu),Hive 在處理有些查詢時(shí)能利用這個(gè)結(jié)構(gòu)。具體而言,連接兩個(gè)在(包含連接列的)相同列上劃分了桶的表,可以使用 Map 端連接 (Map-side join)高效的實(shí)現(xiàn)。比如JOIN操作。對(duì)于JOIN操作兩個(gè)表有一個(gè)相同的列,如果對(duì)這兩個(gè)表都進(jìn)行了桶操作。那么將保存相同列值的桶進(jìn)行JOIN操作就可以,可以大大較少JOIN的數(shù)據(jù)量。

(2)使取樣(sampling)更高效。在處理大規(guī)模數(shù)據(jù)集時(shí),在開發(fā)和修改查詢的階段,如果能在數(shù)據(jù)集的一小部分?jǐn)?shù)據(jù)上試運(yùn)行查詢,會(huì)帶來很多方便。

1. 創(chuàng)建帶桶的 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—個(gè)表應(yīng)該被劃分成桶。我們使用CLUSTERED BY 子句來指定劃分桶所用的列和要?jiǎng)澐值耐暗膫€(gè)數(shù):

CREATE TABLE bucketed_user (id INT) name STRING)
CLUSTERED BY (id) INTO 4 BUCKETS;

在這里,我們使用用戶ID來確定如何劃分桶(Hive使用對(duì)值進(jìn)行哈希并將結(jié)果除 以桶的個(gè)數(shù)取余數(shù)。這樣,任何一桶里都會(huì)有一個(gè)隨機(jī)的用戶集合(PS:其實(shí)也能說是隨機(jī),不是嗎?)。

對(duì)于map端連接的情況,兩個(gè)表以相同方式劃分桶。處理左邊表內(nèi)某個(gè)桶的 mapper知道右邊表內(nèi)相匹配的行在對(duì)應(yīng)的桶內(nèi)。因此,mapper只需要獲取那個(gè)桶 (這只是右邊表內(nèi)存儲(chǔ)數(shù)據(jù)的一小部分)即可進(jìn)行連接。這一優(yōu)化方法并不一定要求 兩個(gè)表必須桶的個(gè)數(shù)相同,兩個(gè)表的桶個(gè)數(shù)是倍數(shù)關(guān)系也可以。用HiveQL對(duì)兩個(gè)劃分了桶的表進(jìn)行連接,可參見“map連接”部分(P400)。

桶中的數(shù)據(jù)可以根據(jù)一個(gè)或多個(gè)列另外進(jìn)行排序。由于這樣對(duì)每個(gè)桶的連接變成了高效的歸并排序(merge-sort), 因此可以進(jìn)一步提升map端連接的效率。以下語法聲明一個(gè)表使其使用排序桶:

CREATE TABLE bucketed_users (id INT, name STRING)
CLUSTERED BY (id) SORTED BY (id ASC) INTO 4 BUCKETS;

我們?nèi)绾伪WC表中的數(shù)據(jù)都劃分成桶了呢?把在Hive外生成的數(shù)據(jù)加載到劃分成 桶的表中,當(dāng)然是可以的。其實(shí)讓Hive來劃分桶更容易。這一操作通常針對(duì)已有的表。

Hive并不檢查數(shù)據(jù)文件中的桶是否和表定義中的桶一致(無論是對(duì)于桶 的數(shù)量或用于劃分桶的列)。如果兩者不匹配,在査詢時(shí)可能會(huì)碰到錯(cuò) 誤或未定義的結(jié)果。因此,建議讓Hive來進(jìn)行劃分桶的操作。

有一個(gè)沒有劃分桶的用戶表:
hive> SELECT * FROM users;
0    Nat
2    Doe
B    Kay
4    Ann
 

2. 強(qiáng)制多個(gè) reduce 進(jìn)行輸出:

要向分桶表中填充成員,需要將 hive.enforce.bucketing 屬性設(shè)置為 true。①這 樣,Hive 就知道用表定義中聲明的數(shù)量來創(chuàng)建桶。然后使用 INSERT 命令即可。需要注意的是: clustered by和sorted by不會(huì)影響數(shù)據(jù)的導(dǎo)入,這意味著,用戶必須自己負(fù)責(zé)數(shù)據(jù)如何如何導(dǎo)入,包括數(shù)據(jù)的分桶和排序。
'set hive.enforce.bucketing = true' 可以自動(dòng)控制上一輪reduce的數(shù)量從而適配bucket的個(gè)數(shù),當(dāng)然,用戶也可以自主設(shè)置mapred.reduce.tasks去適配bucket個(gè)數(shù),推薦使用'set hive.enforce.bucketing = true' 
 

3. 往表中插入數(shù)據(jù):

INSERT OVERWRITE TABLE bucketed_users SELECT * FROM users;

物理上,每個(gè)桶就是表(或分區(qū))目錄里的一個(gè)文件。它的文件名并不重要,但是桶 n 是按照字典序排列的第 n 個(gè)文件。事實(shí)上,桶對(duì)應(yīng)于 MapReduce 的輸出文件分區(qū):一個(gè)作業(yè)產(chǎn)生的桶(輸出文件)和reduce任務(wù)個(gè)數(shù)相同。我們可以通過查看剛才 創(chuàng)建的bucketd_users表的布局來了解這一情況。運(yùn)行如下命令: 
 

4. 查看表的結(jié)構(gòu):

hive> dfs -ls /user/hive/warehouse/bucketed_users;
將顯示有4個(gè)新建的文件。文件名如下(文件名包含時(shí)間戳,由Hive產(chǎn)生,因此 每次運(yùn)行都會(huì)改變):
attempt_201005221636_0016_r_000000_0
attempt_201005221636_0016_r-000001_0
attempt_201005221636_0016_r_000002_0
attempt_201005221636_0016_r_000003_0
第一個(gè)桶里包括用戶IDO和4,因?yàn)橐粋€(gè)INT的哈希值就是這個(gè)整數(shù)本身,在這里 除以桶數(shù)(4)以后的余數(shù):②
 

5. 讀取數(shù)據(jù),看每一個(gè)文件的數(shù)據(jù):

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

用TABLESAMPLE子句對(duì)表進(jìn)行取樣,我們可以獲得相同的結(jié)果。這個(gè)子句會(huì)將 查詢限定在表的一部分桶內(nèi),而不是使用整個(gè)表:

6. 對(duì)桶中的數(shù)據(jù)進(jìn)行采樣:

hive> SELECT * FROM bucketed_users
>    TABLESAMPLE(BUCKET 1 OUT OF 4 ON id);
0 Nat
4 Ann

桶的個(gè)數(shù)從1開始計(jì)數(shù)。因此,前面的查詢從4個(gè)桶的第一個(gè)中獲取所有的用戶。 對(duì)于一個(gè)大規(guī)模的、均勻分布的數(shù)據(jù)集,這會(huì)返回表中約四分之一的數(shù)據(jù)行。我們 也可以用其他比例對(duì)若干個(gè)桶進(jìn)行取樣(因?yàn)槿硬⒉皇且粋€(gè)精確的操作,因此這個(gè) 比例不一定要是桶數(shù)的整數(shù)倍)。例如,下面的查詢返回一半的桶:

7. 查詢一半返回的桶數(shù):

hive> SELECT * FROM bucketed_users
>    TABLESAMPLE(BUCKET 1 OUT OF 2 ON id);
0 Nat
4 Ann
2 Joe

因?yàn)椴樵冎恍枰x取和TABLESAMPLE子句匹配的桶,所以取樣分桶表是非常高效 的操作。如果使用rand()函數(shù)對(duì)沒有劃分成桶的表進(jìn)行取樣,即使只需要讀取很 小一部分樣本,也要掃描整個(gè)輸入數(shù)據(jù)集:

hive〉 SELECT * FROM users
> TABLESAMPLE(BUCKET 1 OUT OF 4 ON rand());
2 Doe

①?gòu)腍ive 0.6.0開始,對(duì)以前的版本,必須把mapred.reduce .tasks設(shè)為表中要填 充的桶的個(gè)數(shù)。如果桶是排序的,還需要把hive.enforce.sorting設(shè)為true。
②顯式原始文件時(shí),因?yàn)榉指糇址且粋€(gè)不能打印的控制字符,因此字段都擠在一起。
 

3、舉個(gè)完整的小栗子:

(1)建student & student1 表:
create table student(id INT, age INT, name STRING)
partitioned by(stat_date STRING) 
clustered by(id) sorted by(age) into 2 buckets
row format delimited fields terminated by ',';

create table student1(id INT, age INT, name STRING)
partitioned by(stat_date STRING) 
clustered by(id) sorted by(age) into 2 buckets
row format delimited fields terminated by ',';
(2)設(shè)置環(huán)境變量:

set hive.enforce.bucketing = true; 
 

(3)插入數(shù)據(jù):
cat bucket.txt

1,20,zxm
2,21,ljz
3,19,cds
4,18,mac
5,22,android
6,23,symbian
7,25,wp

LOAD DATA local INPATH '/home/lijun/bucket.txt' OVERWRITE INTO TABLE student partition(stat_date="20120802");

from student 
insert overwrite table student1 partition(stat_date="20120802") 
select id,age,name where stat_date="20120802">
(4)查看文件目錄:

hadoop fs -ls /hive/warehouse/test.db/student1/stat_date=20120802
Found 2 items
-rw-r--r--   2 lijun supergroup         31 2013-11-24 19:16 /hive/warehouse/test.db/student1/stat_date=20120802/000000_0
-rw-r--r--   2 lijun supergroup         39 2013-11-24 19:16 /hive/warehouse/test.db/student1/stat_date=20120802/000001_0
 

(5)查看sampling數(shù)據(jù):

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

Total MapReduce jobs = 1
Launching Job 1 out of 1
.......
OK
4       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數(shù)的倍數(shù)或者因子。hive根據(jù)y的大小,決定抽樣的比例。例如,table總共分了64份,當(dāng)y=32時(shí),抽取(64/32=)2個(gè)bucket的數(shù)據(jù),當(dāng)y=128時(shí),抽取(64/128=)1/2個(gè)bucket的數(shù)據(jù)。x表示從哪個(gè)bucket開始抽取。例如,table總bucket數(shù)為32,tablesample(bucket 3 out of 16),表示總共抽取(32/16=)2個(gè)bucket的數(shù)據(jù),分別為第3個(gè)bucket和第(3+16=)19個(gè)bucket的數(shù)據(jù)。

感謝各位的閱讀!關(guān)于“Hive中分區(qū)、桶的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI