分桶概念
分桶:并非所有的数据集都可形成合理的分区,特别之前所提到过的要确定合适的划分大小的疑虑。
对于每一个表或者分区,可以进一步细分成桶,桶是对数据进行更细粒度的划分。Hive默认采用对某
一列的每个数据进行hash(哈希),使用hashcode对 桶的个数求余,确定该条记录放入哪个桶中。
分桶实际上和 MapReduce中的分区是一样的。分桶数和reduce数对应。
CREATE [EXTERNAL] TABLE <table_name>
(<col_name> <data_type> [, <col_name> <data_type> ...])]
[PARTITIONED BY ...]
CLUSTERED BY (<col_name>)
[SORTED BY (<col_name> [ASC|DESC] [, <col_name> [ASC|DESC]...])]
INTO <num_buckets> BUCKETS
抽样表: TABLESAMPLE (BUCKET x OUT OF y [ON colname])
colname表示通过哪列进行抽样。colname可以是表中非分区列或者rand()表示对一整行而非单个列进行抽样。表中的记录根据指定的列分桶到y个桶中(从1到y)。返回属于x桶的列。
创建一个32个分桶的表tb1:
hive>create table tb1 (id int,...,...)clustered by (id) into 32 buckets
row format delimited fields terminated by ','
collection items terminated by '-' map keys
terminated by ':' lines terminated by '\n';
我们知道,对于分桶表,是不能使用 load data 的方式进行插入数据的操作的,因为load data 导入数据不会有分桶结构.
为了避免针对桶表使用load data 进行插入数据的操作,我们可以限制对桶表进行load操作,
所以我们要创建一个中间表,通过中间表将数据导入分桶表中。
insert overwrite\into table tb1 select id,... from tbmid;
select * from tb1 tablesample(bucket 3 out of 16 on id);
此条语句挑选32/16=2个桶的数据,从第3个桶开始,为保证数据的多样性,会挑选第3个桶和第(16+3)个桶的数据。
select * from tb1 tablesample(bucket 2 out of 64 on id);
此条语句会挑选32/64=1/2个桶的数据,从第2个桶开始,抽取1/2桶的数据。
开启支持分桶
cli模式下的参数设置只支持本次会话
>set hive.enforce.bucketing=true;
mapreduce会根据bucket的个数自动分配reduce的task个数,(用户也可以通过mapred.reduce.tasks自己设置reduce任务个数,但分桶时不推荐使用)。