抽樣查詢
對於非常大的數據集,用戶不需要全部查詢的結果,只需要一個代表性的查詢結果時,可以通過對錶進行分桶抽樣。
Hive分桶表
先介紹一下Hive桶。
桶是比表或分區更爲細粒度的數據範圍劃分。針對某一列進行桶的組織,對列值哈希,然後除以桶的個數求餘,決定將該條記錄存放到哪個桶中。
好處:
1、獲得更高的查詢處理效率。
2、使抽樣更高效。
創建帶桶的table:
create table bucketed_user(id int ,name string) clustered by (id) into 4 buckets row format delimited fields terminated by '\t' stored as textfile;
使用CLUSTERED BY子句指定使用哪一個列來劃分桶和要劃分的桶的個數。
對於map端連接的情況,兩個表以相同方式劃分桶。處理左邊表內某個桶的mapper知道右邊表內相匹配的行在哪個對應的桶內。因此,mapper只需要獲取那個桶 (這只是右邊表內存儲數據的一小部分)即可進行連接。這一優化方法並不一定要求兩個表必須具有相同個數的桶,兩個表的桶個數是倍數關係也可以。
創建一個排序桶:
create table bucketed_users(id int ,name string) clustered by (id) sorted by (name) into 4 buckets;
查看目錄,發現已經有了bucketed_users這個目錄
hive> dfs -ls /user/hive/warehouse;
Found 4 items
drwxrwxr-x - mahao supergroup 0 2016-09-13 22:59 /user/hive/warehouse/bucketed_users
drwxrwxr-x - mahao supergroup 0 2016-09-12 01:58 /user/hive/warehouse/employees
drwxrwxr-x - mahao supergroup 0 2016-09-08 20:04 /user/hive/warehouse/src
drwxrwxr-x - mahao supergroup 0 2016-09-07 22:26 /user/hive/warehouse/test
桶中的數據根據name列進行排序,在對每個桶進行連接時變成了高效的歸併排序。
Hive不檢測數據文件中的桶是否和表定義中的桶一致(桶數或劃分桶的列),如果不匹配,會在查詢時出錯,所以,建議讓Hive來劃分桶的操作。
向表中插入數據
物理上,一個桶就是表(或分區)目錄裏的一個文件。桶對應於MapReduce的輸出文件分區:一個作業產生的桶(輸出文件)和reduce任務個數相同。
在向分桶表加載數據時,需要先
set hive.enforce.bucketing=true;(hive2.0好像沒有這個參數)
這樣Hive就知道用表定義中聲明的數量來創建桶,然後使用INSERT加載數據即可。
先準備一個沒有劃分桶的表users。
hive> select * from users;
OK
1 zhangsan
2 lisi
3 wangwu
向分桶表中插入數據:
INSERT OVERWRITE TABLE bucketed_users SELECT * FROM users;
查看錶結構:
mahao@ubuntu:~$ hadoop fs -ls /user/hive/warehouse/bucketed_users
Found 4 items
-rwxrwxr-x 1 mahao supergroup 0 2016-09-13 23:36 /user/hive/warehouse/bucketed_users/000000_0
-rwxrwxr-x 1 mahao supergroup 11 2016-09-13 23:36 /user/hive/warehouse/bucketed_users/000001_0
-rwxrwxr-x 1 mahao supergroup 7 2016-09-13 23:36 /user/hive/warehouse/bucketed_users/000002_0
-rwxrwxr-x 1 mahao supergroup 9 2016-09-13 23:36 /user/hive/warehouse/bucketed_users/000003_0
發現有四個文件,即四個桶。
查看文件:
mahao@ubuntu:~$ hadoop fs -cat /user/hive/warehouse/bucketed_users/*0_0;
mahao@ubuntu:~$ hadoop fs -cat /user/hive/warehouse/bucketed_users/*1_0;
1zhangsan
mahao@ubuntu:~$ hadoop fs -cat /user/hive/warehouse/bucketed_users/*2_0;
2lisi
mahao@ubuntu:~$ hadoop fs -cat /user/hive/warehouse/bucketed_users/*3_0;
3wangwu
因爲不會顯示分隔符,所以看着就是挨着的。
抽樣查詢
hive>SELECT * FROM bucketed_users TABLESAMPLE(bucket 1 out of 2 on id);
2 lisi
注: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的數據。