hive分区、分桶

版权声明:版权声明中 https://blog.csdn.net/lds_include/article/details/88757062

hive的分区、分桶

一、分区

1.为什么要分区

  • 当单个表数据量越来越大的时候,hive查询通常会全表扫描,这将会浪费我们不关心数据的扫描,浪费大量时间。从而hive引出分区概念partition

2.怎么分区

  • 看具体业务,能把一堆数据拆分成多个堆的数据就可以。
    通常使用id、年、月、天、区域、省份。

3.hive分区和mysql分区的区别

  • mysql的分区字段采用的表内字段。
  • hive的分区字段使用的是表外字段。

4.hive分区细节

  • 分区本质是在该表下创建对应的目录。
  • 分区名大小写不区分,建议不要使用中文。
  • 可以查询分区信息。但是我们的分区字段相当于是一个伪字段,在元数据中存在,但是不真实存在数据内容中。
  • 加载数据时要指定分区

5.分区操作

  • 关键字:partitioned by
  • 创建一级分区表:
create table if not exists day_part(
uid int,
uname string
)
partitioned by(year int)
row format delimited fields terminated by '\t'
;
load data local inpath '/root/Desktop/student.txt' into table day_part partition(year=2017);
load data local inpath '/root/Desktop/score.txt' into table day_part partition(year=2016);
show partitions day_part;//查看分区
  • 二级分区
create table if not exists day_part1(
uid int,
uname string
)
partitioned by(year int,month int)
row format delimited fields terminated by '\t'
;
load data local inpath '/root/Desktop/student.txt' into table day_part1 partition(year=2017,month=04);
load data local inpath '/root/Desktop/score.txt' into table day_part1 partition(year=2017,month=03);
  • 三级分区:
create table if not exists day_part2(
uid int,
uname string
)
partitioned by(year int,month int,day int)
row format delimited fields terminated by '\t';
load data local inpath '/root/Desktop/student.txt' into table day_part1 partition(year=2017,month=04,day=10);
load data local inpath '/root/Desktop/score.txt' into table day_part1 partition(year=2017,month=03,day=20);
;
  • 对分区进行操作:
    显示分区:
show partitions day_part;
  • 新增分区:空的
alter table day_part1 add partition(year=2017,month=2);
alter table day_part1 add partition(year=2017,month=1) partition(year=2016,month=12);
  • 新增分区并加载数据:
alter table day_part1 add partition(year=2016,month=11) location "/user/hive/warehouse/qf1603.db/day_part1/year=2017/month=2";
  • 修改分区
alter table day_part1 partition(year=2020) rename to partition(year=2018)
  • 修改分区所对应的存储路径:
##路径必须从hdfs写起
alter table day_part1 partition(year=2016,month=11) set location "hdfs://linux1:9000/user/hive/warehouse/qf1603.db/day_part1/year=2017/month=3";
  • 删除分区:删除分区将会删除对应的分区目录(数据)
##删除某个分区
alter table day_part1 drop partition(year=2017,month=2);
##删除多个
alter table day_part1 drop partition(year=2017,month=3),partition(year=2017,month=4);

6.分区的模式

  • 静态分区:新增分区或者是加载分区数据时,已经指定分区名。
  • 动态分区:新增分区或者是加载分区数据时,分区名未知。
  • 混合分区:静态分区和动态分区同时存在。

动态分区的相关属性:

  • hive.exec.dynamic.partition=true :是否允许动态分区
  • hive.exec.dynamic.partition.mode=strict :分区模式设置nostrict strict:最少需要有一个是静态分区 nostrict:可以全部是动态分区
  • hive.exec.max.dynamic.partitions=1000 :允许动态分区的最大数量
  • hive.exec.max.dynamic.partitions.pernode =100 :单个节点上的mapper/reducer允许创建的最大分区

7.创建动态分区:

##创建动态分区表
create table if not exists dyp1(
uid int,
commentid bigint,
recommentid bigint
)
partitioned by(year int,month int,day int)
row format delimited fields terminated by '\t'
;

8.为动态分区加载数据:

##严格模式
insert into table dyp1 partition(year=2016,month,day)
select uid,commentid,recommentid,month,day from tmp;
##非严格模式
##设置非严格模式动态分区
set hive.exec.dynamic.partition.mode=nostrict; 
##创建动态分区表
create table if not exists dyp2(
uid int,
commentid bigint,
recommentid bigint
)
partitioned by(year int,month int,day int)
row format delimited fields terminated by '\t';
##为非严格模式动态分区加载数据
insert into table dyp2 partition(year,month,day)
select uid,commentid,recommentid,year,month,day from tmp;

9.保护措施

hive提供我们一个严格模式:为了阻止用户不小心提交恶意hql
hive.mapred.mode=nostrict : strict
如果该模式值为strict,将会阻止以下三种查询:

  • 1、对分区表查询,where中过滤字段不是分区字段。
  • 2、笛卡尔积join查询,join查询语句,不带on条件 或者 where条件。
  • 3、对order by查询,有order by的查询不带limit语句。

10.注意:

1、尽量不要是用动态分区,因为动态分区的时候,将会为每一个分区分配reducer数量,当分区数量多的时候,reducer数量将会增加,对服务器是一种灾难。
2、动态分区和静态分区的区别,静态分区不管有没有数据都将会创建该分区,动态分区是有结果集将创建,否则不创建。
3、hive动态分区的严格模式和hive提供的hive.mapred.mode的严格模式。

分桶

1.为什么要分桶

  • 分区数据依然很大,对分区数据或者表数据更加细粒度的管理。

2.分桶的意义

  • 1、快速抽样查询。tablesample
  • 2、减少查询扫描数据量,提高查询效率。

3.怎么分桶

  • 对分桶字段进行hash值,然后将hash值模于总的桶数,然后得到桶数

4.分桶的操作

  • 创建分桶表
##创建分桶表,设置4个分桶
create table if not exists bucket7(
uid int,
uname String
)
clustered by(uid) into 4 buckets
row format delimited fields terminated by '\t'
;
  • 设置分桶启用
hive> set hive.enforce.bucketing=true;
  • 为分桶表加载数据:分桶不能使用load方式来加载数据,而需要iinsert into方式来加载
##错误的加载数据方式
load data local inpath '/root/Desktop/student' into table bucket1;
##为分桶表加载数据
insert into table bucket7
select id,name from student
;
  • 分桶查询:
select * from bucket7;
select * from bucket7 tablesample(bucket 1 out of 4 on uid);
select * from bucket7 tablesample(bucket 2 out of 4 on uid);
select * from bucket7 tablesample(bucket 1 out of 2 on uid);
select * from bucket7 tablesample(bucket 2 out of 2 on uid);
select * from bucket7 tablesample(bucket 3 out of 2 on uid);
select * from bucket7 tablesample(bucket 1 out of 8 on uid);
select * from bucket7 tablesample(bucket 5 out of 8 on uid);

5.分区+分桶

  • 操作:创建
##创建表
create table if not exists tmp(
uid int,
uname string,
class int,
gender int)
row format delimited fields terminated by '\t';
##加载数据
load data local inpath '/home/one' into table tmp;
##创建动态分区分桶表
create table if not exists student(
uid int,
uname string,
class int)
partitioned by(gender int)
clustered by(uid) into 2 buckets
row format delimited fields terminated by '\t';
##为动态分区分桶表加载数据
insert into table student partition(gender)
select uid,uname,class,gender from tmp;
  • 操作:查询
select * from student where gender = 2 and uid%2 != 0;
select * from student tablesample(bucket 2 out of 2 on uid) where gender = 2;
  • 注意:分桶使用内部关键字,分区使用的是外部字段。两者都是对hive的一个优化。分区和分桶的数量都要合理设置,不是越多越好。

  • 抽样:

select * from student order by rand() limit 3;
select * from student limit 3;
select * from student tablesample(3 rows);
select * from student tablesample(20B); ##最小单位是B
select * from student tablesample(20 percent);##百分比

猜你喜欢

转载自blog.csdn.net/lds_include/article/details/88757062
今日推荐