為提升hive數(shù)據(jù)的查詢和寫入性能告嘲, hive提供了分區(qū)表機制涤垫。hive每個表格可以指定多個分區(qū)key, 這些分區(qū)key決定數(shù)據(jù)的存儲方式篡诽,比如表格T有個日期型分區(qū)列ds, 表格的數(shù)據(jù)會存儲在:表在hdfs路徑/ds=<date>目錄下路星,查詢語句中ds='2008-09-01'類似過濾條件,可以直接查詢表在hdfs路徑/ds=<date>目錄下數(shù)據(jù)评腺, 達到提升性能的目的帘瞭。
hive提供兩種分區(qū)表:靜態(tài)分區(qū)和動態(tài)分區(qū)。兩者主要的差別在于:加載數(shù)據(jù)的時候蒿讥,動態(tài)分區(qū)不需要指定分區(qū)key的值蝶念, 會根據(jù)key對應列的值自動分區(qū)寫入,如果該列值對應的分區(qū)目錄還沒有創(chuàng)建芋绸, 會自動創(chuàng)建并寫入數(shù)據(jù)媒殉。下面實踐演示:
1.靜態(tài)分區(qū)
創(chuàng)建分區(qū)表
hive >create table teacher(id INT, name string, tno string)
partitioned by (work_date string)
clustered by (id) sorted by (name) into 2 buckets
row format delimited fields terminated by ',' stored as textfile;
靜態(tài)分區(qū)加載數(shù)據(jù)
hive>load data local inpath '/home/warehouse/user.txt' overwrite into table teacher partition(work_date="2016-07-12");
其中user.txt內(nèi)容:
1, t1, 01
2, t2, 02
3, t3, 03
4, t4, 04
分區(qū)創(chuàng)建完成后查看hdfs目錄
hive>dfs -ls /user/hive/warehouse/crwal_db.db/teacher/
drwxrwxrwx - warehouse supergroup 0 2016-07-12 09:03 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-07-12
可以看出創(chuàng)建的分區(qū)目錄
2.動態(tài)分區(qū)
首先需要設置參數(shù): 動態(tài)分區(qū)相關參數(shù)設置如下
set hive.exec.dynamic.partition=true;(可通過這個語句查看:set hive.exec.dynamic.partition;)
set hive.exec.dynamic.partition.mode=nonstrict; (strict要求至少有一個靜態(tài)分區(qū), nonstrict可以都是動態(tài)分區(qū))
set hive.exec.max.dynamic.partitions=100000;(如果自動分區(qū)數(shù)大于這個參數(shù)摔敛,將會報錯)
set hive.exec.max.dynamic.partitions.pernode=100000;
創(chuàng)建一個臨時表格适袜, 用于加載數(shù)據(jù), 然后把臨時表格的數(shù)據(jù)插入到分區(qū)表舷夺。
hive>create table tmp (
id int, name string, tno string, work_date string)
row format delimited fields terminated by ',' stored as textfile;
本地文件數(shù)據(jù)
$ cat user1.txt
1,root,01,2016-07-11
2,sys,02,2016-07-11
3,user01,03,2016-07-11
4,user02,04,2016-07-11
5,user03,05,2016-07-11
6,user04,06,2016-06-11
7,user05,07,2016-06-11
8,user06,08,2016-06-11
9,user07,09,2016-06-11
10,user08,10,2016-05-11
11,user09,11,2016-05-11
12,user10,12,2016-05-11
加載數(shù)據(jù)到臨時表
load data local inpath "/home/warehouse/user1.txt" overwrite into table tmp;
從臨時表加載數(shù)據(jù)到分區(qū)表
hive>insert into table teacher partition(work_date) select id, name, tno, work_date from tmp;
再次查看hdfs中數(shù)據(jù)分區(qū)
hive>dfs -ls /user/hive/warehouse/crwal_db.db/teacher/
drwxrwxrwx - warehouse supergroup 0 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-05-11
drwxrwxrwx - warehouse supergroup 0 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-06-11
drwxrwxrwx - warehouse supergroup 0 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-07-11
上面的臨時表work_date包括三個數(shù)據(jù):2016-05-11, 2016-06-11售貌, 2016-07-11,插入到以workdate為分區(qū)key的teacher表時, 會自動識別出這三種值次洼,分別創(chuàng)建三個目錄犬缨。而不需要像靜態(tài)分區(qū)一樣每插入一個分區(qū)key的數(shù)據(jù)都要一條如下插入語句:
insert into table teacher partition(work_date="2016-05-11") select id, name, tno, work_date from tmp where work_date="2016-05-11";
需要注意的是:
在一個表同時使用動態(tài)和靜態(tài)分區(qū)表時, 靜態(tài)分區(qū)值必須在動態(tài)分區(qū)值的前面恒削。
選擇分區(qū)key時池颈,要防止數(shù)據(jù)傾斜, 數(shù)據(jù)嚴重分布不均衡钓丰。
使用動態(tài)分區(qū)躯砰, 作為分區(qū)列的值要可以預測和枚舉, 不能目錄過多而每個目錄數(shù)據(jù)又很少携丁,會嚴重影響性能琢歇。
3.桶
對于每一個表(table)或者分區(qū),Hive可以進一步組織成桶。Hive也是針對某一列進行桶的組織李茫。Hive采用對列值哈希揭保,然后除以桶的個數(shù)求余的方式?jīng)Q定該條記錄存放在哪個桶當中。采用桶好處有兩個:
- 數(shù)據(jù)sampling2. 提升某些查詢操作效率魄宏,例如mapside join
JOIN操作兩個表有一個相同的列秸侣,如果對這兩個表都進行了桶操作。那么將保存相同列值的桶進行JOIN操作就可以宠互,可以大大較少JOIN的數(shù)據(jù)量味榛。
hive >create table teacher(id INT, name string, tno string)
partitioned by (work_date string)
clustered by (id) sorted by (name) into 2 buckets
row format delimited fields terminated by ',' stored as textfile;
hive中table可以拆分成partition,table和partition可以通過‘CLUSTERED BY ’進一步分bucket名秀,bucket中的數(shù)據(jù)可以通過‘SORT BY’排序励负。如上語句所示, 通過id列把數(shù)據(jù)分成2個桶匕得, 桶中數(shù)據(jù)通過name排序继榆。
可以看下分區(qū)表里面分成桶以后的文件存儲格式:
hive>dfs -ls /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-06-11;
-rwxrwxrwx 3 warehouse supergroup 24 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-06-11/000000_0
-rwxrwxrwx 3 warehouse supergroup 24 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-06-11/000001_0
可見每個分區(qū)數(shù)據(jù)被劃分到了兩個桶里面。
下面看下桶在數(shù)據(jù)采樣里面的應用:
tablesample是抽樣語句汁掠,語法:TABLESAMPLE(BUCKET x OUT OF y)
select * from teacher tablesample(bucket 1 out of 2 on id);