hive中有桶的概念,對於每一個表或者分區,可以進一步組織成桶,說白點,就是更細粒度的數據范圍。
hive采用列值哈希,然后除以桶的個數以求余的方式決定該條記錄存放在哪個桶當中。
使用桶的好處:
1、獲得更高的查詢處理效率。桶為表加上了額外的結構,Hive在處理有些查詢時能利用這個結構。具體而言,連接兩個在(包含連接列的)相同列上划分了桶的表,可以使用 Map 端連接 (Map-side join)高效的實現。比如JOIN操作。對於JOIN操作兩個表有一個相同的列,如果對這兩個表都進行了桶操作。那么將保存相同列值的桶進行JOIN操作就可以,可以大大較少JOIN的數據量。
2、使取樣(sampling)更高效。在處理大規模數據集時,在開發和修改查詢的階段,如果能在數據集的一小部分數據上試運行查詢,會帶來很多方便。
需要特別注意的是:clustered by和sorted by不會影響數據的導入,這意味着,用戶必須自己負責數據如何如何導入,包括數據的分桶和排序。
可以使用'set hive.enforce.bucketing = true'
可以自動控制上一輪reduce的數量從而適配bucket的個數,
看個例子
原始數據
1 15 xiaohong 2 16 xiaoming 3 17 xiaohuang 3 18 xiaocui 4 19 xiaoma 5 21 xiaocai 6 22 xiaojie 7 25 xiaoliu 8 28 xaoqi
先創建一張普通表,再創建一張桶的表。
create table student(id INT, age INT, name STRING)
partitioned by(p_date STRING)
row format delimited fields terminated by '\t';
create table bucketed_student(id INT, age INT, name STRING)
partitioned by(stat_date STRING)
clustered by(id) sorted by(age) into 2 bucket
row format delimited fields terminated by '\t';
load數據到普通表,因為直接load到分桶的表是不會分桶,需要insert進行才會根據根據分桶要求進行分桶。
LOAD DATA LOCAL INPATH '/home//aaa' OVERWRITE INTO table bucketed_student partition(p_date='2016');
set hive.enforce.bucketing = true;
insert overwrite table bucketed_student partition(p_date='2016') select id,age,name from student where p_date=2016
查看兩表的目錄,發現分桶會生成兩份數據文件
hadoop fs -ls /data/hive/warehouse/temp.db/bucketed_student/p_date=2016
Found 2 items
-rwxr-xr-x 3 webopa hive 50 2016-11-23 13:53 /data/hive/warehouse/temp.db/bucketed_student/p_date=2016/000000_0
-rwxr-xr-x 3 webopa hive 68 2016-11-23 13:53 /data/hive/warehouse/temp.db/bucketed_student/p_date=2016/000001_0
普通表是一份
hadoop fs -ls /data/hive/warehouse/temp.db/student/p_date=2016 Found 1 items -rwxrwxrwx 3 webopa hive 117 2016-11-23 11:41 /data/hive/warehouse/temp.db/student/p_date=2016/aaa
查看下分通表每個文件中的數據。偶數一個文件,基數一個文件。
hadoop fs -cat /data/hive/warehouse/temp.db/bucketed_student/p_date=2016/000000_0 8 28 xaoqi 6 22 xiaojie 4 19 xiaoma 2 16 xiaoming hadoop fs -cat /data/hive/warehouse/temp.db/bucketed_student/p_date=2016/000001_0 7 25 xiaoliu 5 21 xiaocai 3 18 xiaocui 3 17 xiaohuang 1 15 xiaohong
查看sampling數據:
select * from bucketed_student tablesample(bucket 1 out of 2 on id); 8 28 xaoqi 2016 6 22 xiaojie 2016 4 19 xiaoma 2016 2 16 xiaoming 2016
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的數據
