一、桶的概念:
对于每一个表(table)或者分区, Hive可以进一步组织成桶,
也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。Hive采用
对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
把表(或者分区)组织成桶(Bucket)有两个理由:
(1)、获得更高的查询处理效率。
(2)、使取样(sampling)更高效。
强制多个 reduce 进行输出:
插入数据前需设置,不设置将会只有一个文件:
set hive.enforce.bucketing=true;
要向分桶表中填充数据,需要将 hive.enforce.bucketing 属性设置为 true。
这 样,Hive 就知道用表定义中声明的数量来创建桶。然后使用 INSERT 命令即可。
需要注意的是: clustered by和sorted by不会影响数据的导入,这意味着,用户必须自己负责数据如何如何导入,包括数据的分桶和排序。
‘set hive.enforce.bucketing = true’ 可以自动控制上一轮reduce的数量从而适配bucket的个数,
当然,用户也可以自主设置mapred.reduce.tasks去适配bucket个数,推荐使用’set hive.enforce.bucketing = true’
二、操作
(1)、分桶案例:
a、创建普通表:
create table if not exists stu(
eNo int,
name string,
sex string,
age int
)
row format delimited fields terminated by'\t'
stored as textfile;
创建一个文件
vi stu.txt
1 xiaoA nan 21
2 xiaoB nv 24
3 xiaoC nan 21
4 xiaoD nan 21
5 xiaoE nan 21
6 xiaoF nv 26
7 xiaoG nan 21
8 xiaoH nan 21
9 xiaoI nv 27
10 xiaoJ nv 29
11 xiaoK nan 21
12 xiaoM nv 21
将文件数据导入hive表中
load data local inpath '/home/hadoop/data/stu.txt' overwrite into table stu;
b、创建分桶表(对stu表的eNo字段分桶)
注意:分桶字段和分区字段区别
create table if not exists bk_stu(
eNo int,
name string,
sex string,
age int
)
clustered by(eNo) into 4 buckets
row format delimited fields terminated by'\t'
stored as textfile;
注意:
强制多个 reduce 进行输出:
插入数据前需设置,不设置将会只有一个文件:
set hive.enforce.bucketing = true
要向分桶表中填充数据,需要将 hive.enforce.bucketing 属性设置为 true。
这 样,Hive 就知道用表定义中声明的数量来创建桶。
c、从普通表将数据插入到分桶表(注意;插入数据到分桶表时,只能以结果集
的方式插入数据)。
insert into table bk_stu select * from stu;
从hive查看hdfs中的数据方法
hive> dfs -ls hdfs:///user/hive/warehouse/zl.db;
Found 9 items
drwxr-xr-x - zl supergroup 0 2022-04-21 15:48 hdfs:///user/hive/warehouse/zl.db/bucket_stu
drwxr-xr-x - zl supergroup 0 2022-04-15 23:01 hdfs:///user/hive/warehouse/zl.db/flowsum
drwxr-xr-x - zl supergroup 0 2022-04-15 22:45 hdfs:///user/hive/warehouse/zl.db/person
drwxr-xr-x - zl supergroup 0 2022-04-17 13:21 hdfs:///user/hive/warehouse/zl.db/pt_flow
drwxr-xr-x - zl supergroup 0 2022-04-21 15:04 hdfs:///user/hive/warehouse/zl.db/pv
drwxr-xr-x - zl supergroup 0 2022-04-16 16:13 hdfs:///user/hive/warehouse/zl.db/tb_regexp_log
drwxr-xr-x - zl supergroup 0 2022-04-15 22:45 hdfs:///user/hive/warehouse/zl.db/ticket
drwxr-xr-x - zl supergroup 0 2022-04-17 14:45 hdfs:///user/hive/warehouse/zl.db/user01
drwxr-xr-x - zl supergroup 0 2022-04-17 14:22 hdfs:///user/hive/warehouse/zl.db/users
查看分桶,可以看到,分桶的数据
hive> dfs -ls hdfs:///user/hive/warehouse/zl.db/bucket_stu;
Found 2 items
-rwxr-xr-x 2 zl supergroup 60 2022-04-21 15:48 hdfs:///user/hive/warehouse/zl.db/bucket_stu/000000_0
-rwxr-xr-x 2 zl supergroup 71 2022-04-21 15:48 hdfs:///user/hive/warehouse/zl.db/bucket_stu/000001_0
抽样数据结果如下
hive> select * from bucket_stu;
OK
10 oo nan 22
8 mm nv 29
6 ff nan 20
4 dd nan 23
2 bb nvn 21
11 ss nan 20
9 nn nan 28
7 gg nan 20
5 ee nv 22
3 cc nan 24
1 aa nv 19
那么如何从分好的桶中取数据呢
注:tablesample是抽样语句,
语法:TABLESAMPLE(BUCKET x OUT OF y)
y必须是table总bucket数的倍数或者因子。
hive根据y的大小,决定抽样的比例。
例如,table总共分了64份:clustered by(eNo) into 64 buckets
当y=32时,抽取(64/32=)2个bucket的数据
当y=128时,抽取(64/128=)1/2个bucket的数据。
x表示从哪个bucket开始抽取。
例如,table总bucket数为32:clustered by(eNo) into 32 buckets
tablesample(bucket 3 out of 16)
表示总共抽取(32/16=)2个bucket的数据,
分别为第3个bucket和第(3+16=)19个bucket的数据。
分桶表查询方式:
clustered by(eNo) into 4 buckets
(1)、随机查询并且返回一桶数据:
select * from bk_stu tablesample(bucket 3 out of 4);
(2)、随机查询并且返回两桶数据:
select * from bk_stu tablesample(bucket 1 out of 2);
(3)、随机查询并且返回全桶数据:
select * from bk_stu tablesample(bucket 1 out of 1);
(4)、随机查询并且返回半桶数据:
select * from bk_stu tablesample(bucket 3 out of 8);
三、分桶总结
抽样查询======================
分桶表:bk_stu
普通表:stu
#随机从某表中取10条数据:
select * from stu order by rand() limit 3;
11 xiaoK nan 21
3 xiaoC nan 21
4 xiaoD nan 21
Time taken: 114.053 seconds, Fetched: 3 row(s)select * from bk_stu tablesample(bucket 1 out of 4 on eNo);
OK
12 xiaoM nv 21
8 xiaoH nan 21
4 xiaoD nan 21
Time taken: 1.567 seconds, Fetched: 3 row(s)
对比时间:分桶表查询的速度肯定比普通表块!
#数据块取样 (TABLESAMPLE (n PERCENT))抽取表大小的n%
select * from bk_stu tablesample(50 PERCENT);
select * from bk_stu tablesample(25 PERCENT);#指定数据大小取样(TABLESAMPLE (nM)) M为MB单位
select * from bk_stu tablesample(1M);#指定抽取条数(TABLESAMPLE (n ROWS))
select * from bk_stu tablesample(4ROWS);