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)中存在,通過describetable命令可以查看到字段存在, 但是該字段不存放實(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 fieldsterminated by '' 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 inviteswhere ds ='2013-08-12';
5. 往一個(gè)分區(qū)表的某一個(gè)分區(qū)中添加數(shù)據(jù):
insert overwrite tableinvites partition (ds='2013-08-12') select id,max(name) from test group by id;
可以查看分區(qū)的具體情況,使用命令:
hadoop fs -ls /home/hadoop.hive/warehouse/invites
或者:
show partitionstablename;
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 tablebucketed_user(id int,name string)clustered by (id) sorted by(name) into 4buckets row format delimited fields terminated by '' 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 4BUCKETS; 在這里,我們使用用戶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)行劃分桶的操作。
2. 往表中插入數(shù)據(jù):
INSERT OVERWRITE TABLEbucketed_users SELECT * FROM users; 物理上,每個(gè)桶就是表(
或分區(qū))目錄里的一個(gè)文件。它的文件名并不重要,但是桶 n 是按照字典序排列的第 n 個(gè)文件。
事實(shí)上,桶對(duì)應(yīng)于 MapReduce
的輸出文件分區(qū):一個(gè)作業(yè)產(chǎn)生的桶(輸出文件)和reduce任務(wù)個(gè)數(shù)相同.
3. 對(duì)桶中的數(shù)據(jù)進(jìn)行采樣:
hive> SELECT * FROMbucketed_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ù)倍)。
注:tablesample是抽樣語句,語法:TABLESAMPLE(BUCKET x OUTOF 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ù)。
總結(jié)
分區(qū)按照我們指定列范圍進(jìn)行分區(qū)(層級(jí)文件夾),而分桶是按照列值的hash值,這樣想同值都會(huì)在一個(gè)桶內(nèi)(一級(jí)文件夾內(nèi)不同文件區(qū)別不同的桶),便于join操作。
最后,小編整理了更多hive,大數(shù)據(jù)相關(guān)的學(xué)習(xí)資料可以分享給大家
轉(zhuǎn)發(fā) 關(guān)注后,++我vx:bmaaa01? 獲取