不多说,直接上干货!
Hive还可以把表或分区,组织成桶。将表或分区组织成桶有以下几个目的:
第一个目的是为看取样更高效,因为在处理大规模的数据集时,在开发、测试阶段将所有的数据全部处理一遍可能不太现实,这时取样就必不可少。
第二个目的是为了获得更好的查询处理效率。
桶为了表提供了额外的结构,Hive在处理某些查询时利用这个结构,能给有效地提高查询效率。
桶是通过对指定列进行哈希计算来实现的,通过哈希值将一个列名下的数据切分为一组桶,并使每个桶对应于该列名下的一个存储文件。
在建立桶之前,需要设置hive.enforce.bucketing属性为true,使得hive能识别桶。
以下为创建带有桶的表的语句:
CREATE TABLE bucketed_user( id INT, name String ) CLUSTERED BY (id) INTO 4 BUCKETS;
向桶中插入数据,这里按照用户id分成了4个桶,在插入数据时对应4个reduce操作,输出4个文件。
分区中的数据可以被进一步拆分成桶,bucket,不同于分区对列直接进行拆分,桶往往使用列的哈希值进行数据采样。
在分区数量过于庞大以至于可能导致文件系统崩溃时,建议使用桶。
桶的数量是固定的。
Hive使用基于列的哈希函数对数据打散,并分发到各个不同的桶中从而完成数据的分桶过程。
注意,hive使用对分桶所用的值进行hash,并用hash结果除以桶的个数做取余运算的方式来分桶,保证了每个桶中都有数据,但每个桶中的数据条数不一定相等。
哈希函数的选择依赖于桶操作所针对的列的数据类型。除了数据采样,桶操作也可以用来实现高效的Map端连接操作。
记住,分桶比分区,更高的查询效率。
如何进行桶操作?
例子1
1、创建临时表 student_tmp,并导入数据。
hive> desc student_tmp; hive> select * from student_tmp;
2、创建 student 表。经过分区操作过后的表已经被拆分成2个桶。
create table 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 ',';
分区中的数据可以被进一步拆分成桶!!!正确理解
所有,桶,先partitioned by (stat_date string)
,再,clustered by (id) sorted by(age) into 2 bucket
3、设置环境变量。
hive> set hive.enforce.bucketing=true;
4、插入数据
hive> from student_tmp insert overwrite table student partition(stat_date='2015-01-19') select id,age,name where stat_date='2015-01-18' sort by age;
这都是固定的格式,一环扣一环的。
5、查看文件目录
$ hadoop fs -ls /usr/hive/warehouse/student/stat_date=2015-01-19/
6、查看 sampling 数据。
tablesample 是抽样语句,语法如下
tablesample(bucket x out of y)
y 必须是 table 中 BUCKET 总数的倍数或者因子。
例子2
在下面的例子中,经过分区操作过后的表已经被拆分成100个桶。
CREATE EXTERNAL TABLE videos_b( prodicer string, title string, category string ) PARTITIONED BY(year int) CLUSTERED BY(title)INTO 100 BUCKETS;
现在,我们开始填充这张带桶操作的表:
set hive.enfirce.bucketinig=true; FROM videos INSERT OVERWRITE TABLE videos_b PARTITION(year=1999) SELECT producer,title,string WHERE year=2009;
如果不使用set hive.enforce.bucketing=true这项属性,我们需要显式地声明set mapred.reduce.tasks=100来设置Reducer的数量。
此外,还需要在SELECT语句后面加上CLUSTERBY来实现INSERT查询。
下面是不使用桶设置的例子:
set mapred.reduce.tasks=100; FROM videos INSERT OVERWRITE TABLE videos_b PARTITION(year=1999) SELECT producer,title,string WHERE year=2009 CLUSTER BY title;
在Hive的文档中可以找到有关桶的更多细节:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL