大数据开发学习1.6-Hive的分区、分桶表和压缩存储

196 阅读7分钟

分区表

​ 分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过where子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。

分区表基本操作

创建分区表语法

create table dept_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/datas/dept_20220401.log' 
into table dept_partition 
partition(day='20220401');

load data local inpath '/opt/module/hive/datas/dept_20220402.log' 
into table dept_partition 
partition(day='20220402');

load data local inpath '/opt/module/hive/datas/dept_20220403.log' 
into table dept_partition 
partition(day='20220403');

注意:分区表加载数据时,必须指定分区

查询分区表中数据

  • 单分区查询
select 
    * 
from dept_partition 
where day='20220401';
  • 多分区查询
select 
	* 
from dept_partition 
where day='20220401'
union
select 
	* 
from dept_partition
where day='20220402'

查看分区表有多少分区

show partitions dept_partition;

增加分区

  • 创建单个分区
alter table dept_partition 
add partition(day='20220404');
  • 同时创建多个分区(分区之间不能有逗号)
alter table dept_partition
add partition(day='20220405') partition(day='20220406');

删除分区

  • 删除单个分区
alter table dept_partition 
drop partition (day='20220406');
  • 同时删除多个分区(分区之间必须有逗号)
alter table dept_partition 
drop partition (day='20220404'), partition(day='20220405');

分区表二级分区

创建二级分区表

create table dept_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/datas/dept_20220401.log' 
into table dept_partition2 
partition(day='20220401', hour='12');
  • 查询分区数据
select 
*
from dept_partition2 
where day='20220401' and hour='12';

把数据直接上传到分区目录上,让分区表和数据产生关联的三种方式

方式一:上传数据后修复

  1. 上传数据
dfs -mkdir -p  /user/hive/warehouse/dept_partition2/day=20220401/hour=13
dfs -put /opt/module/hive/datas/dept_20220401.log  /user/hive/warehouse/dept_partition2/day=20220401/hour=13;
  1. 查询数据(查询不到刚上传的数据)
select 
 * 
 from dept_partition2
 where day='20220401' and hour='13';
  1. 执行修复命令
msck repair table dept_partition2;
  1. 再次查询数据
select 
*
from dept_partition2 
where day='20220401' and hour='13';

方式二:上传数据后添加分区

  1. 上传数据
dfs -mkdir -p  /user/hive/warehouse/dept_partition2/day=20220401/hour=14;
dfs -put /opt/module/hive/datas/dept_20220401.log  /user/hive/warehouse/dept_partition2/day=20220401/hour=14;
  1. 执行添加分区
alter table dept_partition2 
add partition(day='20220401',hour='14');
  1. 查询数据
select 
*
from dept_partition2 
where day='20220401' and hour='14';

方式三:创建文件夹后load数据到分区

  1. 创建目录
dfs -mkdir -p  /user/hive/warehouse/dept_partition2/day=20220401/hour=15;
  1. 上传数据
load data local inpath '/opt/module/hive/datas/dept_20220401.log' 
into table dept_partition2 
partition(day='20220401',hour='15');
  1. 查询数据
select
*
from dept_partition2
where day='20220401' and hour='15';

动态分区调整

​ 关系型数据库中,对分区表Insert数据时候,数据库自动会根据分区字段的值,将数据插入到相应的分区中,Hive中也提供了类似的机制,即动态分区(Dynamic Partition),只不过,使用Hive的动态分区,需要进行相应的配置。

开启动态分区参数设置

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

    hive.exec.dynamic.partition=true
    
  • 设置为非严格模式(动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区)

    hive.exec.dynamic.partition.mode=nonstrict
    
  • 在所有执行MapReduce的节点上,最大一共可以创建多少个动态分区。默认1000。

    hive.exec.max.dynamic.partitions=1000
    
  • 在每个执行MapReduce的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错。

    hive.exec.max.dynamic.partitions.pernode=100
    
  • 整个MapReduce Job中,最大可以创建多少个HDFS文件。默认100000。

    hive.exec.max.created.files=100000
    
  • 当有空分区生成时,是否抛出异常。一般不需要设置。默认false。

    hive.error.on.empty.partition=false
    

实例

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

分桶表

​ 分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区。对于一张表或者分区,Hive 可以进一步组织成桶,也就是更为细粒度的数据范围划分。

​ 分桶是将数据集分解成更容易管理的若干部分的另一个技术。

​ 分区针对的是数据的存储路径;分桶针对的是数据文件。

创建分桶表

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

创建排序分桶表(桶内数据排序)

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

压缩和存储

Hadoop压缩配置

MapReduce支持的压缩编码

压缩格式算法文件扩展名是否可切分
DEFLATEDEFLATE.deflate
GzipDEFLATE.gz
bzip2bzip2.bz2
LZOLZO.lzo
SnappySnappy.snappy

为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器,如下表所示:

Hadoop查看支持压缩的方式hadoop checknative。

Hadoop在driver端设置压缩。

压缩格式对应的编码/解码器
DEFLATEorg.apache.hadoop.io.compress.DefaultCodec
gziporg.apache.hadoop.io.compress.GzipCodec
bzip2org.apache.hadoop.io.compress.BZip2Codec
LZOcom.hadoop.compression.lzo.LzopCodec
Snappyorg.apache.hadoop.io.compress.SnappyCodec

压缩参数配置

参数默认值阶段建议
io.compression.codecs (在core-site.xml中配置)org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec, org.apache.hadoop.io.compress.Lz4Codec输入压缩Hadoop使用文件扩展名判断是否支持某种编解码器
mapreduce.map.output.compressfalseMapper输出这个参数设为true启用压缩
mapreduce.map.output.compress.codecorg.apache.hadoop.io.compress.DefaultCodecMapper输出使用LZO、LZ4或snappy编解码器在此阶段压缩数据
mapreduce.output.fileoutputformat.compressfalseReducer输出这个参数设为true启用压缩
mapreduce.output.fileoutputformat.compress.codecorg.apache.hadoop.io.compress. DefaultCodecReducer输出使用标准工具或者编解码器,如gzip和bzip2

开启Map输出阶段压缩

  1. 开启Hive中间传输数据压缩功能(Hive本身也希望自己控制下压缩)
set hive.exec.compress.intermediate=true;
  1. 开启MapReduce中Map输出压缩功能
set mapreduce.map.output.compress=true;
  1. 设置MapReduce中Map输出数据的压缩方式
set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;

开启Reduce输出阶段压缩

当Hive将输出写入到表中时,输出内容同样可以进行压缩。属性hive.exec.compress.output控制着这个功能。用户可能需要保持默认设置文件中的默认值false,这样默认的输出就是非压缩的纯文本文件了。用户可以通过在查询语句或执行脚本中设置这个值为true,来开启输出结果压缩功能。

  1. 开启Hive最终输出数据压缩功能(Hive希望能自己控制压缩)
set hive.exec.compress.output=true;
  1. 开启MapReduce最终输出数据压缩
set mapreduce.output.fileoutputformat.compress=true;
  1. 设置MapReduce最终数据输出压缩方式
set mapreduce.output.fileoutputformat.compress.codec =org.apache.hadoop.io.compress.SnappyCodec;

文件存储格式

Hive支持的存储数据的格式主要有:textfile 、sequencefile、orc、parquet

列式存储和行式存储

image-20220826195642617.png

  • 行存储的特点 查询满足条件的一整行数据的时候,列存储则需要去每个聚集的字段找到对应的每个列的值,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快。

  • 列存储的特点

    ​ 因为每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量;每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。

textfilesequencefile的存储格式都是基于行存储的

orcparquet是基于列式存储的