一、hive分桶
概述
hive 分桶
分桶表是对列值取哈希值的方式,将不同数据放到不同文件中存储。
对于hive中每一个表、分区都可以进一步进行分桶。
由列的哈希值除以桶的个数求余的方式来决定每条数据划分在哪个桶中。
适用场景:
数据抽样( sampling )、map-join
数据抽样:
数据抽样要保证数据的均匀性,而不是一部分极端的数据,分桶表是对列值取哈希值的方式,能保证数据的均匀分布;
map-join:
获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,
可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存
相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
开启支持分桶
开启支持分桶:
set hive.enforce.bucketing=true;
默认:false;设置为true之后,mr运行时会根据bucket的个数自动分配reduce task个数。
(用户也可以通过mapred.reduce.tasks自己设置reduce任务个数,但分桶时不推荐使用)
注意:一次作业产生的桶(文件数量)应该和reduce task个数一致。
hive (default)> set hive.enforce.bucketing; #查看是否开启 hive.enforce.bucketing=false
hive (default)> set hive.enforce.bucketing=true; #开启分桶
hive (default)> set hive.enforce.bucketing; hive.enforce.bucketing=true
往分桶表中加载数据语法
insert into table bucket_table select columns from tbl;
insert overwrite table bucket_table select columns from tbl;
分桶抽样语法
桶表 抽样查询
select * from bucket_table tablesample(bucket 1 out of 4 on columns);
TABLESAMPLE语法:
TABLESAMPLE(BUCKET x OUT OF y)
x:表示从哪个bucket开始抽取数据
y:必须为该表总bucket数的倍数或因子
例1:
当表总bucket数为32时:
TABLESAMPLE(BUCKET 3 OUT OF 4),抽取哪些数据?
桶总数有32
x=2,从第二个桶开始取数据;
y=4,桶的因子或倍数
要抽取数据:8份(32/4)
2,6,10,14,18,22,26,30
例2:
当表总bucket数为32时:
TABLESAMPLE(BUCKET 3 OUT OF 256),抽取哪些数据?
桶总数有32
x=3,从第3个桶开始取数据;
y=256,桶的因子或倍数
要抽取数据:1/8份数据(32/256)
从3号桶取1/8数据
二、hive分桶案例
创建原始数据表并导入数据
hive (default)> CREATE TABLE psn31( id INT, name STRING, age INT)
> ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
OK
Time taken: 0.838 seconds
[root@hadoop-senior ~]# cat data4
1,tom,11
2,cat,22
3,dog,33
4,hive,44
5,hbase,55
6,mr,66
7,alice,77
8,scala,88
hive (default)> load data local inpath '/root/data4' into table psn31;
hive (default)> select * from psn31;
OK
psn31.id psn31.name psn31.age
1 tom 11
2 cat 22
3 dog 33
4 hive 44
5 hbase 55
6 mr 66
7 alice 77
8 scala 88
Time taken: 0.028 seconds, Fetched: 8 row(s)
创建分桶表并加载数据
hive (default)> CREATE TABLE psnbucket( id INT, name STRING, age INT)
> CLUSTERED BY (age) INTO 4 BUCKETS
> ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
OK
Time taken: 0.032 seconds
hive (default)> insert into table psnbucket select id, name, age from psn31;
hive (default)> select * from psnbucket;
OK
psnbucket.id psnbucket.name psnbucket.age
8 scala 88
4 hive 44
7 alice 77
3 dog 33
6 mr 66
2 cat 22
5 hbase 55
1 tom 11
Time taken: 0.049 seconds, Fetched: 8 row(s)
查看分桶情况
##可见分了四个桶,桶号:1, 2, 3, 4
[root@hadoop-senior modules]# hadoop-2.5.0/bin/hdfs dfs -ls /user/hive/warehouse/psnbucket
Found 4 items
-rw-r--r-- 1 root supergroup 21 2019-08-27 14:43 /user/hive/warehouse/psnbucket/000000_0
-rw-r--r-- 1 root supergroup 20 2019-08-27 14:43 /user/hive/warehouse/psnbucket/000001_0
-rw-r--r-- 1 root supergroup 17 2019-08-27 14:43 /user/hive/warehouse/psnbucket/000002_0
-rw-r--r-- 1 root supergroup 20 2019-08-27 14:43 /user/hive/warehouse/psnbucket/000003_0
##查看桶中的数据
[root@hadoop-senior modules]# hadoop-2.5.0/bin/hdfs dfs -text /user/hive/warehouse/psnbucket/000000_0
8,scala,88
4,hive,44
[root@hadoop-senior modules]# hadoop-2.5.0/bin/hdfs dfs -text /user/hive/warehouse/psnbucket/000001_0
7,alice,77
3,dog,33
[root@hadoop-senior modules]# hadoop-2.5.0/bin/hdfs dfs -text /user/hive/warehouse/psnbucket/000002_0
6,mr,66
2,cat,22
[root@hadoop-senior modules]# hadoop-2.5.0/bin/hdfs dfs -text /user/hive/warehouse/psnbucket/000003_0
5,hbase,55
1,tom,11
开始抽样
##抽样第二个桶的数据,可见抽样出来的数据和上面查看的第二个桶的数据一样
hive (default)> select id, name, age from psnbucket tablesample(bucket 2 out of 4 on age);
OK
id name age
7 alice 77
3 dog 33
Time taken: 0.073 seconds, Fetched: 2 row(s)