Hive分桶一文读懂

什么是分桶?

和分区一样,分桶也是一种通过改变表的存储模式,从而完成对表优化的一种调优方式。

但和分区不同的是,分区是将表拆分到不同的子目录中进行存储,而分桶是将表拆分到不同文件中进行存储。

那什么是分桶呢?它按分桶键哈希取模的方式,将表中数据随机、均匀地分发到若干桶文件中。

比如,对表的ID字段进行分桶,那ID字段被称为分桶键。ID字段存储的数据假设是1-10,执行分桶操作时,需要确定要分几个桶,这里定为3个;那么便会对分桶键中的值,按照桶的数量进行哈希取模,这里即对桶数3进行取余。

那么,ID为3、6、9的数据会存放到第一个桶中,ID为1、4、7、10的会存放到第二个桶中,ID为2、5、8的则存放到第三个桶中。而每个桶在进行存储的时候,会存储为一个桶文件。

分桶目的

那分桶操作的目的是什么呢?它通过改变数据的存储分布,提升查询、取样、Join等特定任务的执行效率。

因为分桶之后,在数据查询中,根据分桶键的过滤条件,就可以直接通过哈希取模来确定数据存放的桶文件,从而减少需要处理的数据量;在海量数据场景中,能极大提升数据处理效率。而在数据取样过程中,可以直接对某几个桶文件进行取样,缩短取样时间。

其次,如果在Hive中,两张表需要进行join操作,转换为MapReduce或Spark作业之后,必定要经过Shuffle,而Shuffle过程会耗费大量时间,从而拉低了处理效率。但两张表,假设使用ID进行Join,而且都使用ID作为分桶键进行了分桶操作,分桶数也相同,均为3;那么便可以直接对两张表的对应桶文件直接进行join处理,提升处理效率。因为ID相同的数据,按照相同的方式进行哈希取模,必定会存放到相同的桶文件中。

所以当两张表的桶数相同或成倍数时,会带来join效率的提升。

分区和分桶是两种不同的优化手段,当然也可以同时进行,即先分区后分桶;最终的存储效果便是在子目录下的数据,被存储为多个桶文件。

分桶表的创建

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  
    [ROW FORMAT <row_format>] 
    [LOCATION '<file_path>']    
    [TBLPROPERTIES ('<property_name>'='<property_value>', ...)];

例如,现创建一张分桶表tb_buckets,包含字段id、name、age,将id作为分桶键,分桶数为3:

create table tb_buckets(
id int,
name string,
age int
)
clustered by (id) into 3 buckets
stored as textfile;

分桶后,数据存放时默认按分桶键升序。如果需要为桶文件进行自定义排序,则可以使用SORTED BY进行设定。

例如,创建分桶表tb_buckets_desc,包含字段id、name、age,将id作为分桶键,分桶数为3,在桶中按ID降序排列:

create table tb_buckets_desc(
id int,
name string,
age int
)
clustered by (id) 
sorted by (id desc)
into 3 buckets
stored as textfile;

分桶表数据插入

分桶表创建完成后,可以插入数据:

--再次强调,Hive不建议单条插入,会生成小文件,这里只是方便演示
insert into table tb_buckets values(1, 'zs', 18);
insert into table tb_buckets values(2, 'ls', 18);
insert into table tb_buckets values(3, 'ls', 18);
insert into table tb_buckets values(4, 'ls', 18);

但是,在数据插入之后,在HDFS中查看数据文件,却发现是4个文件,而且没有桶文件的区分:

那么说明,在数据插入时,不会自动分桶。而必须要开启配置:

set hive.enforce.bucketing=true;

参数默认值为false;设置为true之后,mr运行时会根据bucket桶的个数自动分配reduce task个数。一次作业产生的桶(文件数量)和reduce task个数 一致。这个参数在2.x版本之前,不需要进行设置。

当然用户也可以通过mapred.reduce.tasks自己设置reduce任务个数,但分桶时不推荐使用。

为了对比,设置分桶的配置参数后,向tb_buckets_desc表插入相同的数据:

--开启配置
set hive.enforce.bucketing=true;
--插入数据
insert into table tb_buckets_desc values(1, 'zs', 18);
insert into table tb_buckets_desc values(2, 'ls', 18);
insert into table tb_buckets_desc values(3, 'ls', 18);
insert into table tb_buckets_desc values(4, 'ls', 18);

数据插入后,再进入到HDFS中进行查看,可以看到虽然文件数较多,因为TextFile仅支持追加,每插入一次数据便会生成一个文件,但桶已经可以区分出来了。

结束语

如果有帮助的,记得点赞、关注。在公众号《数舟》中,可以免费获取专栏《数据仓库》配套的视频课程、大数据集群自动安装脚本,并获取进群交流的途径。

我所有的大数据技术内容也会优先发布到公众号中。如果对某些大数据技术有兴趣,但没有充足的时间,在群里提出,我为大家安排分享。

公众号自取:

公众号

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桥路丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值