久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

Hive中分區、桶的示例分析

146次閱讀
沒有評論

共計 5726 個字符,預計需要花費 15 分鐘才能閱讀完成。

這篇文章給大家分享的是有關 Hive 中分區、桶的示例分析的內容。丸趣 TV 小編覺得挺實用的,因此分享給大家做個參考,一起跟隨丸趣 TV 小編過來看看吧。

1、Hive 分區表

在 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;

2、Hive 桶

對于每一個表(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:其實也能說是隨機,不是嗎?)。

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

桶中的數據可以根據一個或多個列另外進行排序。由于這樣對每個桶的連接變成了高效的歸并排序(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。
②顯式原始文件時,因為分隔字符是一個不能打印的控制字符,因此字段都擠在一起。
 

3、舉個完整的小栗子:(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)設置環境變量:

set hive.enforce.bucketing = true; 
 

(3)插入數據:

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 數據:

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 數的倍數或者因子。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 的數據。

感謝各位的閱讀!關于“Hive 中分區、桶的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-16發表,共計5726字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 岳阳市| 湾仔区| 进贤县| 于田县| 淄博市| 马山县| 疏附县| 普格县| 长乐市| 博湖县| 和平县| 张家港市| 霍林郭勒市| 都安| 黄冈市| 门源| 清流县| 襄垣县| 永泰县| 湘潭县| 织金县| 彩票| 涡阳县| 通许县| 南宁市| 徐闻县| 布拖县| 绿春县| 温泉县| 柯坪县| 泸定县| 惠安县| 霍州市| 崇礼县| 沿河| 贵州省| 防城港市| 屯昌县| 沈阳市| 新昌县| 佛冈县|