Hive中的分区就是把一张大表的数据按照业务需要分散存储到多个目录,每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区,这样的查询效率会提高很多。
分区表基本语法
1、建表语句
hive (default)>
create table dept_partition
(
deptno int, --部门编号
dname string, --部门名称
loc string --部门位置
)
partitioned by (day string)
row format delimited fields terminated by '\t';
2、分区表写数据
# load 方式
hive (default)>
load data local inpath '/home/hadoop/data/dept_20230401.log'
into table dept_partition
partition(day='20230401');
# insert
hive (default)>
insert overwrite table dept_partition partition (day = '20230402')
select deptno, dname, loc
from dept_partition
where day = '2023-04-01';
3、分区表读数据
查询分区表数据时,可以将分区字段看作表的伪列,可像使用其他字段一样使用分区字段。
select deptno, dname, loc ,day
from dept_partition
where day = '2020-04-01';
4、分区表基本操作
# 查看所有分区信息
hive> show partitions dept_partition;
# 创建单个分区
hive (default)> alter table dept_partition add partition(day='20220403');
# 同时创建多个分区(分区之间不能有逗号)
hive (default)> alter table dept_partition add partition(day='20220404') partition(day='20220405');
# 删除单个分区
hive (default)> alter table dept_partition drop partition (day='20220403');
# 同时删除多个分区(分区之间必须有逗号)
hive (default)> alter table dept_partition drop partition (day='20220404'), partition(day='20220405');
Hive将分区表的所有分区信息都保存在了元数据中,只有元数据与HDFS上的分区路径一致时,分区表才能正常读写数据。若用户手动创建/删除分区路径,Hive都是感知不到的,这样就会导致Hive的元数据和HDFS的分区路径不一致。再比如,若分区表为外部表,用户执行drop partition命令后,分区元数据会被删除,而HDFS的分区路径不会被删除,同样会导致Hive的元数据和HDFS的分区路径不一致。
若出现元数据和HDFS路径不一致的情况,可通过如下几种手段进行修复。
- add partition:若手动创建HDFS的分区路径,Hive无法识别,可通过add partition命令增加分区元数据信息,从而使元数据和分区路径保持一致。
- drop partition:若手动删除HDFS的分区路径,Hive无法识别,可通过drop partition命令删除分区元数据信息,从而使元数据和分区路径保持一致。
- msck:若分区元数据和HDFS的分区路径不一致,还可使用msck命令进行修复
hive (default)> msck repair table table_name [add/drop/sync partitions];
# msck repair table table_name add partitions:该命令会增加HDFS路径存在但元数据缺失的分区信息。
# msck repair table table_name drop partitions:该命令会删除HDFS路径已经删除但元数据仍然存在的分区信息。
# msck repair table table_name sync partitions:该命令会同步HDFS路径和元数据分区信息,相当于同时执行上述的两个命令。
# msck repair table table_name:等价于msck repair table table_name add partitions命令。
二级分区表
如果一天内的日志数据量很大,如何再将数据拆分?答案是二级分区表,例如可以在按天分区的基础上,再对每天的数据按小时进行分区。
基本语法
# 创建表
hive (default)>
create table dept_partition2(
deptno int, -- 部门编号
dname string, -- 部门名称
loc string -- 部门位置
)
partitioned by (day string, hour string)
row format delimited fields terminated by '\t';
# 数据装载语句
hive (default)>
load data local inpath '/hoem/hadoop/data/dept_20230401.log'
into table dept_partition2
partition(day='20230401', hour='12');
# 查询分区数据
hive (default)>
select
*
from dept_partition2
where day='20220401' and hour='12';
动态分区
动态分区是指向分区表insert数据时,被写往的分区不由用户指定,而是由每行数据的最后一个字段的值来动态的决定。使用动态分区,只用一个insert语句将数据写入多个分区。
# 动态分区功能总开关(默认true,开启)
set hive.exec.dynamic.partition=true
# 动态分区的模式,默认strict(严格模式),要求必须指定至少一个分区为静态分区,nonstrict(非严格模式)允许所有的分区字段都使用动态分区。
set hive.exec.dynamic.partition.mode=nonstrict
# 一条insert语句可同时创建的最大的分区个数,默认为1000。
set hive.exec.max.dynamic.partitions=1000
# 单个Mapper或者Reducer可同时创建的最大的分区个数,默认为100。
set hive.exec.max.dynamic.partitions.pernode=100
# 一条insert语句可以创建的最大的文件个数,默认100000。
set hive.exec.max.created.files=100000
# 当查询结果为空时且进行动态分区时,是否抛出异常,默认false。
hive.error.on.empty.partition=false