压缩和存储
1. Hadoop
压缩配置
https://blog.csdn.net/qq_42735631/article/details/116903553
1.1 开启 Map
输出阶段压缩
- 开启
hive
中间传输数据压缩功能set hive.exec.compress.intermediate=true;
- 开启
mapreduce
中map
输出压缩功能set mapreduce.map.output.compress=true;
- 设置
mapreduce
中map
输出数据的压缩方式set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;
- 执行查询语句
-
未开启压缩
-
开启压缩
-
1.2 开启 Reduce
输出阶段压缩
- 开启
hive
最终输出数据压缩功能set hive.exec.compress.output=true;
- 开启
mapreduce
最终输出数据压缩set mapreduce.output.fileoutputformat.compress=true;
- 设置
mapreduce
最终数据输出压缩方式set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
- 设置
mapreduce
最终数据输出压缩为块压缩set mapreduce.output.fileoutputformat.compress.type=BLOCK;
- 测试一下输出结果是否是压缩文件
insert overwrite local directory '/opt/module/hive-3.1.2/datas/distribute-result' select * from emp distribute by deptno sort by empno desc;
2. 文件存储格式
Hive
支持的存储数据的格式主要有:TEXTFILE
、SEQUENCEFILE
、ORC
、PARQUET
2.1 列式存储和行式存储
- 行存储的特点:
- 查询满足条件的一整行数据的时候,列存储则需要去每个聚集的字段找到对应的每个列的值,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快。
- 列存储的特点
- 因为每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量;每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。
-
TEXTFILE
和SEQUENCEFILE
的存储格式都是基于行存储的;ORC
和PARQUET
是基于列式存储的。
2.2 TextFile
格式
默认格式,数据不做压缩,磁盘开销大,数据解析开销大。可结合 Gzip
、Bzip2
使用,但使用 Gzip
这种方式,hive
不会对数据进行切分,从而无法对数据进行并行操作。
2.3 Orc
格式
Index Data
- 一个轻量级的 index,默认是每隔 1W 行做一个索引。这里做的索引应该只是记录某行的各字段在 Row Data 中的 offset
Row Data
- 存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个
Stream
来存储
- 存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个
Stripe Footer
- 存的是各个
Stream
的类型,长度等信息。
- 存的是各个
每个文件有一个 File Footer
,这里面存的是每个 Stripe
的行数,每个 Column
的数据类型信息等;每个文件的尾部是一个 PostScript
,这里面记录了整个文件的压缩类型以及FileFooter
的长度信息等。在读取文件时,会 seek
到文件尾部读 PostScript
,从里面解析到File Footer
长度,再读 FileFooter
,从里面解析到各个 Stripe
信息,再读各个 Stripe
,即从后往前读。
2.4 Parquet
格式
Parquet 文件是以二进制方式存储的,所以是不可以直接读取的,文件中包括该文件的数据和元数据,因此 Parquet 格式文件是自解析的。
- 行组
Row Group
:- 每一个行组包含一定的行数,在一个
HDFS
文件中至少存储一
个行组,类似于orc
的stripe
的概念
- 每一个行组包含一定的行数,在一个
- 列块
Column Chunk
:- 在一个行组中每一列保存在一个列块中,行组中的所有列连
续的存储在这个行组文件中。一个列块中的值都是相同类型的,不同的列块可能使用不同的算法进行压缩
- 在一个行组中每一列保存在一个列块中,行组中的所有列连
- 页
Page
:- 每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式
通常情况下,在存储 Parquet
数据的时候会按照 Block
大小设置行组的大小,由于一般情况下每一个 Mapper
任务处理数据的最小单位是一个 Block,这样可以把每一个行组由一个Mapper
任务处理,增大任务执行并行度。
3. 存储格式对比实验
-
TextFile
// 创建数据格式为 textfile的表 create table if not exists log_text ( track_time string, url string, session_id string, referer string, id string, end_user_id string, city_id string ) row format delimited fields terminated by '\t' stored as textfile ; load data local inpath '/opt/module/hive-3.1.2/datas/log.data' into table log_text;
-
ORC
// 创建数据格式为ocr的表 create table if not exists log_orc ( track_time string, url string, session_id string, referer string, id string, end_user_id string, city_id string ) row format delimited fields terminated by '\t' stored as orc tblproperties ("orc.compress"="NONE"); insert into table log_orc select * from log_text;
-
Parquet
// 创建数据格式为parquet的表 create table if not exists log_parquet ( track_time string, url string, session_id string, referer string, id string, end_user_id string, city_id string ) row format delimited fields terminated by '\t' stored as parquet ; insert into table log_parquet select * from log_text;
实验结果表示:ORC
> Parquet
> textFile
4. 存储和压缩结合实验对比
-
创建一个
ZLIB
压缩的ORC
存储方式// 创建一个数据格式为ocr,压缩格式为zlib的表 create table if not exists log_ocr_zlib ( track_time string, url string, session_id string, referer string, id string, end_user_id string, city_id string ) row format delimited fields terminated by '\t' stored as orc tblproperties ("orc.compress"="ZLIB"); insert into table log_ocr_zlib select * from log_text;
-
创建一个
SNAPPY
压缩的ORC
存储方式// 创建一个数据格式为orc,压缩格式为snappy的表 create table if not exists log_ocr_snappy ( track_time string, url string, session_id string, referer string, id string, end_user_id string, city_id string ) row format delimited fields terminated by '\t' stored as orc tblproperties ("orc.compress"="SNAPPY"); insert into table log_ocr_snappy select * from log_text;
-
创建一个
SNAPPY
压缩的parquet
存储方式// 创建一个数据格式为parquet,压缩格式为snappy的表 create table if not exists log_parquet_snappy ( track_time string, url string, session_id string, referer string, id string, end_user_id string, city_id string ) row format delimited fields terminated by '\t' stored as parquet tblproperties ("parquet.compression"="SNAPPY");