Hive分区(Partition)和桶(Bucket)

介绍

HIve做为数据仓库,往往会存储大量数据。当数据量过大时,会大大降低查询和统计效率。为了解决这个问题提出了分区(Partition)概念,将数据按照一定的规则进行分区,这样需要读取数据时,就可以直接扫面某个分区下的数据,避免全表扫描,提高了查询统计效率。例如按照地区(省份)进行分区,北京地区数据会落到一个分区目录中,天津地区数据落到另一个分区目录中,当要查询北京/天津地区数据时,直接扫描北京/天津分区目录,大大缩短了查询时间。

分区表创建

分区表创建方式有两种,静态分区和动态分区。二者区别在于是否手动创建分区,静态分区需要在插入数据前使用add partition命令添加分区,动态分区只需要在插入数据insert命令中指定分区字段即可。因此在存在大量分区时使用动态分区比较方便,不需要手动创建这些分区。

create table test(id int, name string) partitioned by (year int);

注意:分区表创建时分区字段不需要单独做为column指定,只需要在partitioned by()中指定字段和类型即可,多个分区字段用“,”隔开

插入数据

数据插入成功后,会在warehouse(HDFS)上创建对应分区目录,例如/hive/warehouse/test/year=2020,/hive/warehouse/test/year=2019等分区目录。

静态分区

先手动添加分区

alter table test add partition(year=2020);

然后插入数据

insert into test partition(year=2020) values(1,'tom');

动态分区

动态分区默认是关闭的,需要修改相关参数。

//分区模式设置为nostrict
hive.exec.dynamic.partition.mode=nonstrict      //默认strict
hive.exec.dynamic.partition=true                //是否开启动态分区,默认true
//为了避免失误造成生成太多分区,以下参数可以做限制
hive.exec.max.dynamic.partitions=1000		    //最大动态分区数,默认1000
hive.exec.max.dynamic.partitions.pernode=100    //每个mapper/reducer生成最大分区数
hive.exec.max.created.files=100000              //所有mapper/reducer生成最大文件数
hive.error.on.empty.partition=false             //空结果是否抛出异常

插入数据

insert into test partition(year) values(1,'tom',2020);

注意:无论是insert values还是insert select方式插入数据,partition对应的值要按顺序放到最后
insert overwrite语句会覆盖整个分区数据,原来数据被清空

查询分区数据

select * from test where year=2020

删除分区

删除某个分区后,该分区和分区下数据全部删除,不影响其他分区

alter table drop partition(year=2020)

桶(Bucket)

当某个分区数据量越来越大时,查询性能仍然会降低。为了解决这个问题提出了桶(Bucket)概念,桶相当于分区来说是更加细粒度的划分。它按照某个字段进行hash划分,将字段值取hash,然后对桶个数取余运算,即hash(value)%buckets,按照最后计算值决定数据存入哪个桶中。

注意:使用分桶需要先调整参数,set hive.enforce.bucketing = true设置reduce数量自动匹配桶个数;或者主动设置reduce数量匹配桶的个数set mapreduce.job.reduces=桶个数.
2.x版本后无需设置此参数

按桶的使用方式分为三种:
1、仅分桶(Bucket)
建表

//按照id字段分为3个桶
create table test(id int,name string) clustered by(id) into 3 buckets;

2、分桶和排序混合(Bucket & Sorted)

//桶内数据按照sorted by()指定字段按照升序排序,方便查询
create table test(id int,name string) clustered by(id) sorted by(name) into 3 buckets;

3、分区和分桶混合(Partitioned & Bucket)

create table test(id int,name string) partition by(year) clustered by(id) sorted by(name) into 3 buckets;

插入

alter table test add partition(year=2020);
insert into/overwrite test values(1,'tom');

查询

查询桶表数据有特定的语法,在平常的查询语句后边增加特定语法:
TABLESAMPLE (BUCKET x OUT OF y [ON colname]) 官网参考资料

TABLESAMPLE表示抽样查询。
y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了64buckets,当y=32时,抽取(64/32=)2个bucket的数据,当y=128时,抽取(64/128=)1/2个bucket的数据。
x表示从哪个bucket开始抽取。例如,table总bucket数为32,tablesample(bucket 3 out of 16),表示总共抽取(32/16=)2个bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据。

//查询第一个桶的数据
select * from test tablesample(1 out of 3 on id)
//表示抽取3/3=1个桶的数据,从第1个桶开始

水平一般,能力有限,大数据小学生一枚。文章主要用于个人学习和总结,如果能给他人带来帮助,纯属意外。

你可能感兴趣的:(Hive)