打怪升级之小白的大数据之旅(六十六)<Hive旅程第七站:Hive的分区表与分桶表>

Posted GaryLea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了打怪升级之小白的大数据之旅(六十六)<Hive旅程第七站:Hive的分区表与分桶表>相关的知识,希望对你有一定的参考价值。

打怪升级之小白的大数据之旅(六十六)

Hive旅程第七站:Hive的分区表与分桶表

上次回顾

上一章,我们学习了Hive的查询相关语法,本章节我们学习一下分区表与分桶表

分区表

  • 通过前面Hive的学习,我们知道,表在HDFS中其实就是一个文件夹,而具体的映射关系是由metastore元数据来做的
  • 分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。
  • Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。
  • 在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多
  • 分区表加载数据时,必须指定分区

分区表基本操作

创建分区表

测试数据(模拟根据日期生成的日志信息)

# 第一个log文件与数据
vim /opt/module/hive/dbdata/logs/dept_20210530.log
10	ACCOUNTING	1700
20	RESEARCH	1800
# 第二个log文件与数据
vim /opt/module/hive/dbdata/logs/dept_20210531.log
30	SALES	1900
40	OPERATIONS	1700
# 第三个log文件与数据
vim /opt/module/hive/dbdata/logs/dept_20210601.log
50	TEST	2000
60	DEV	1900

创建分区表

create table dept_log_partition(
deptno int, dname string, loc string)
partitioned by (day string)
row format delimited fields terminated by '\\t';

加载数据到分区表中

load data local inpath "/opt/module/hive/dbdata/logs/dept_20210530.log" into table dept_log_partition partition(day="2021-05-30");

load data local inpath "/opt/module/hive/dbdata/logs/dept_20210531.log" into table dept_log_partition partition(day="2021-05-31");

load data local inpath "/opt/module/hive/dbdata/logs/dept_20210601.log" into table dept_log_partition partition(day="2021-06-01");

查询分区表中数据

查询分区表中数据

-- 查询当前分区表中所有数据
select * from dept_log_partition;

单分区查询

-- 查询2021-05-30的数据
select * from dept_log_partition where day='2021-05-30';

多分区联合查询(查询2021-05-30和2021-05-31的数据)

-- 第一种方法
select * from dept_log_partition 
where day='2021-05-30'
union
select * from dept_log_partition 
where day='2021-05-31';

-- 第二种方法
select * from dept_log_partition 
where day='2021-05-30' or
day='2021-05-31';	
  • 上面两种方法,第一种会调用MR程序,运行效率比较慢,第二种直接查询,不会进行MR程序,效率比较快

查看分区表中的分区信息

show partitions dept_log_partition;

查看分区表结构

desc formatted dept_log_partition;

增加分区

  • 创建单个分区
alter table dept_log_partition add partition(day='2021-06-02');
  • 创建多个分区,分区间不能使用,,需要使用空格
alter table dept_log_partition add partition(day='2021-06-03') partition(day='2021-06-04');

删除分区

  • 删除单个分区
alter table dept_log_partition drop partition(day='2021-06-02') ;
  • 删除多个分区,分区间必须使用,
alter table dept_log_partition drop partition(day='2021-06-03'),partition(day='2021-06-04');

分区表二级分区

前面我们是模拟按照每天的log日志进行分区存储,如果我们数据量依旧很大,那么我们可以在每天的分区下,再创建一个按照小时的分区,此时就需要学习一下二级分区

创建二级分区表

create table dept_log_partition2(
deptno int, dname string, loc string)
partitioned by (day string, hour string)
row format delimited fields terminated by '\\t';

加载数据到二级分区表中

load data local inpath '/opt/module/hive/dbdata/logs/dept_20210530.log' into table
dept_log_partition2 partition(day='2021-05-30', hour='12');

查询分区数据

select * from dept_log_partition2 where day='2021-05-30' and hour='12';

数据直接上传到一级分区目录并进行数据关联的方式

  • 还记得在创建表时,我们直接将数据上传到HDFS中存储该表的文件夹下,没有使用Load进行加载,数据依旧可以读取到么?虽然它可以读取到数据,但是它并没有与元数据进行绑定
  • 在分区表中,如果直接将数据上传到分区表并不进行元数据绑定的话,我是无法查询到数据的,所以我们需要将数据与元数据进行绑定

数据绑定方式一 上传数据后进行修复

上传数据

-- 在HDFS上创建一个分区表的文件夹
dfs -mkdir -p /user/hive/warehouse/test.db/dept_log_partition2/day=2021-05-30/hour=13;

-- 上传数据到HDFS中
dfs -put /opt/module/hive/dbdata/logs/dept_20210530.log /user/hive/warehouse/test.db/dept_log_partition2/day=2021-05-30/hour=13;

查询数据(此时因为没有与元数据绑定,所以分区表中查不到该数据)

select * from dept_log_partition2 where day='2021-05-30' and hour='13';

执行修复命令

msck repair table dept_log_partition2;

再次查询,此时可以发现;成功查询到数据了

select * from dept_log_partition2 where day='2021-05-30' and hour='13';

数据绑定方式二 上传数据后再添加分区

上传数据

 -- 在HDFS上创建一个分区表的文件夹
dfs -mkdir -p /user/hive/warehouse/test.db/dept_log_partition2/day=2021-05-30/hour=14;

-- -- 上传数据到该文件夹下
dfs -put /opt/module/dbdata/logs/dept_20210530.log /user/hive/warehouse/test.db/dept_log_partition2/day=2021-05-30/hour=14;

添加分区

alter table dept_log_partition2 add partition(day='2021-05-30',hour='14');

查询数据

select * from dept_log_partition2 where day='2021-05-30' and hour='14';

使用load加载数据到分区中

创建分区目录

dfs -mkdir -p /user/hive/warehouse/test.db/dept_log_partition2/day=2021-05-30/hour=15;

加载数据

load data local inpath '/opt/module/hive/dbdata/logs/dept_20210530.log' into table
 dept_log_partition2 partition(day='2021-05-30',hour='15');

查询数据

select * from dept_log_partition2 where day='2021-05-30' and hour='15';

动态分区

  • 前面我们使用的手动进行分区,下面我来介绍一下动态分区,所谓动态分区,它也是依旧一个条件(例如时间)来进行动态创建分区,有了动态分区,可以很方便地管理我们的数据
  • 使用动态分区还需要一些相关的配置

动态分区配置

补充两个知识点:

  • 严格模式后面会讲到
  • 动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区
  • 建议下面的配置使用临时设置 set 下面的参数

开启动态分区功能(默认开启: true)

hive.exec.dynamic.partition=true;

设置为非严格模式为 nonstrict

hive.exec.dynamic.partition.mode=nonstrict;

设置整个MR节点上的动态分区最大值

hive.exec.max.dynamic.partitions=1000;

设置单个MR节点上的动态分区最大值,假设我们想按照天来进行动态分区,那么就设置值为365

hive.exec.max.dynamic.partitions.pernode=365;

设置整个MR Job的HDFS最大文件数量

hive.exec.max.created.files=100000;

设置空分区异常配置,设置为true时,当有空分区生成就会抛出异常

hive.error.on.empty.partition=false;

示例:将dept表中的数据按照地区(loc字段),插入到目标表dept_partition的相应分区中

-- 创建分区表
create table dept_partition_dy(id int, name string) partitioned by (loc int) row format delimited fields terminated by '\\t';
-- 设置动态分区
insert into table dept_partition_dy partition(loc) select deptno, dname, loc from dept;
-- 查看分区表情况
show partitions dept_partition_dy;

分桶表

  • 分区提供一个隔离数据和优化查询的便利方式
  • 不过,并非所有的数据集都可形成合理的分区
  • 对于一张表或者分区,Hive 可以进一步组织成桶,也就是更为细粒度的数据范围划分
  • 分桶是将数据集分解成更容易管理的若干部分的另一个技术
  • 分区针对的是数据的存储路径;分桶针对的是数据文件
  • Hive的分桶采用对分桶字段的值进行哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中

示例:先创建分桶表,通过直接导入数据文件的方式

数据准备(在HDFS上创建测试数据):

-- 现在本地创建测试数据
vim /opt/module/hive/dbdata/buck/buckData.txt 
1001	ss1
1002	ss2
1003	ss3
1004	ss4
1005	ss5
1006	ss6
1007	ss7
1008	ss8
1009	ss9
1010	ss10
1011	ss11
1012	ss12
1013	ss13
1014	ss14
1015	ss15
1016	ss16

-- 在HDFS中创建一个存储数据的文件夹
dfs -mkdir -p /user/hive/warehouse/db_hive.db/buckdata
-- 将测试数据放到HDFS中
dfs -put /opt/module/hive/dbdata/buck/buckData.txt   /user/hive/warehouse/test.db/buckdata;

创建分桶表

create table log_buck(id int, name string)
clustered by(id) 
into 4 buckets
row format delimited fields terminated by '\\t';

查看表结构

desc formatted stu_buck;

导入数据到分桶表中

load data inpath '/user/hive/warehouse/test.db/buckdata/' into table log_buck;

查看分桶数据

select * from log_buck;

总结

本章节介绍了分区表和分桶表,在实际开发中,分区表分桶表也是对数据的一种优化策略,可以加快我们的查询效率,因为我们可以直接通过分区来查找数据而不是遍历整个数据

以上是关于打怪升级之小白的大数据之旅(六十六)<Hive旅程第七站:Hive的分区表与分桶表>的主要内容,如果未能解决你的问题,请参考以下文章

打怪升级之小白的大数据之旅(六十)<Hive旅程中的始发站>

打怪升级之小白的大数据之旅(六十)<Hive旅程中的始发站>

打怪升级之小白的大数据之旅(六十一)<Hive旅程第二站:Hive安装>

打怪升级之小白的大数据之旅(六十一)<Hive旅程第二站:Hive安装>

打怪升级之小白的大数据之旅(六十二)<Hive旅程第三站:Hive数据类型>

打怪升级之小白的大数据之旅(六十二)<Hive旅程第三站:Hive数据类型>