背景:
1)已经创建好了4张不同类型的表
2)清理hxh2,hxh3,hxh4表的数据,保留hxh1里面的数据,hxh1的表数据大小为:74.1GB
3)同时创建hxh5表和hxh1一样都是TEXTFILE存储类型
4)原始数据大小:74.1 G
开始测试:
1、TextFile测试
- Hive数据表的默认格式,存储方式:行存储。
- 可以使用Gzip压缩算法,但压缩后的文件不支持split
- 在反序列化过程中,必须逐个字符判断是不是分隔符和行结束符,因此反序列化开销会比SequenceFile高几十倍。
开启压缩:
- set hive.exec.compress.output=true; --启用压缩格式
- set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec; --指定输出的压缩格式为Gzip
- set mapred.output.compress=true; --开启mapred输出结果进行压缩
- set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec; --选用GZIP进行压缩
向hxh5表插入数据:
insert into table hxh5 partition(createdate="2019-07-21") select pvid,sgid,fr,ffr,mod,version,vendor from hxh1;
进行压缩后的hxh5表数据大小:23.8 G,消耗:81.329 seconds
2、Sequence File测试
- 压缩数据文件可以节省磁盘空间,但Hadoop中有些原生压缩文件的缺点之一就是不支持分割。支持分割的文件可以并行的有多个mapper程序处理大数据文件,大多数文件不支持可分割是因为这些文件只能从头开始读。Sequence File是可分割的文件格式,支持Hadoop的block级压缩。
- Hadoop API提供的一种二进制文件,以key-value的形式序列化到文件中。存储方式:行存储。
- sequencefile支持三种压缩选择:NONE,RECORD,BLOCK。Record压缩率低,RECORD是默认选项,通常BLOCK会带来较RECORD更好的压缩性能。
- 优势是文件和hadoop api中的MapFile是相互兼容的
开启压缩:
- set hive.exec.compress.output=true; --启用压缩格式
- set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec; --指定输出的压缩格式为Gzip
- set mapred.output.compression.type=BLOCK; --压缩选项设置为BLOCK
- set mapred.output.compress=true;
- set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;
向hxh2表中插入数据:
insert into table hxh2 partition(createdate="2019-07-21") select pvid,sgid,fr,ffr,mod,version,vendor from hxh1;
进行压缩后的hxh2表数据大小:80.8 G,消耗:186.495 seconds //未进行type类型设置,默认是Record
进行压缩后的hxh2表数据大小:25.2 G,消耗:81.67 seconds //设置type类型为BLOCK
3、RCFile测试
存储方式:数据按行分块,每块按列存储。结合了行存储和列存储的优点:
- 首先,RCFile 保证同一行的数据位于同一节点,因此元组重构的开销很低
- 其次,像列存储一样,RCFile 能够利用列维度的数据压缩,并且能跳过不必要的列读取
- 数据追加:RCFile不支持任意方式的数据写操作,仅提供一种追加接口,这是因为底层的 HDFS当前仅仅支持数据追加写文件尾部。
- 行组大小:行组变大有助于提高数据压缩的效率,但是可能会损害数据的读取性能,因为这样增加了Lazy 解压性能的消耗。而且行组变大会占用更多的内存,这会影响并发执行的其他MR作业。 考虑到存储空间和查询效率两个方面,Facebook 选择 4MB 作为默认的行组大小,当然也允许用户自行选择参数进行配置。
开启压缩:
- set hive.exec.compress.output=true;
- set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
- set mapred.output.compress=true;
- set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;
向hxh3表中插入数据:
insert into table hxh3 partition(createdate="2019-07-01") select pvid,sgid,fr,ffr,mod,version,vendor from hxh1;
进行压缩后的表大小:22.5 G,消耗时间:136.659 seconds
4、ORC测试
存储方式:数据按行分块,每块按照列存储。
压缩快,快速列存取。效率比rcfile高,是rcfile的改良版本。
开启压缩:
- set hive.exec.compress.output=true;
- set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
- set mapred.output.compress=true;
- set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;
向hxh4表中插入数据:
insert into table hxh4 partition(createdate="2019-07-01") select pvid,sgid,fr,ffr,mod,version,vendor from hxh1;
进行压缩后的表大小:21.9 G,消耗时间:76.602 seconds
5、什么是可分割
在考虑如何压缩那些将由MapReduce处理的数据时,考虑压缩格式是否支持分割是很重要的。考虑存储在HDFS中的未压缩的文件,其大小为1GB,HDFS的块大小为64MB,所以该文件将被存储为16块,将此文件用作输入的MapReduce作业会创建1个输人分片(split,也称为“分块”。对于block,我们统一称为“块”。)每个分片都被作为一个独立map任务的输入单独进行处理。
现在假设,该文件是一个gzip格式的压缩文件,压缩后的大小为1GB。和前面一样,HDFS将此文件存储为16块。然而,针对每一块创建一个分块是没有用的,因为不可能从gzip数据流中的任意点开始读取,map任务也不可能独立于其他分块只读取一个分块中的数据。gzip格式使用DEFLATE来存储压缩过的数据,DEFLATE将数据作为一系列压缩过的块进行存储。问题是,每块的开始没有指定用户在数据流中任意点定位到下一个块的起始位置,而是其自身与数据流同步。因此,gzip不支持分割(块)机制。
在这种情况下,MapReduce不分割gzip格式的文件,因为它知道输入是gzip压缩格式的(通过文件扩展名得知),而gzip压缩机制不支持分割机制。因此一个map任务将处理16个HDFS块,且大都不是map的本地数据。与此同时,因为map任务少,所以作业分割的粒度不够细,从而导致运行时间变长。
6、压缩模式说明
1. 压缩模式评价
可使用以下三种标准对压缩方式进行评价:
- 压缩比:压缩比越高,压缩后文件越小,所以压缩比越高越好。
- 压缩时间:越快越好。
- 已经压缩的格式文件是否可以再分割:可以分割的格式允许单一文件由多个Mapper程序处理,可以更好的并行化。
2. 压缩模式对比
- BZip2有最高的压缩比但也会带来更高的CPU开销,Gzip较BZip2次之。如果基于磁盘利用率和I/O考虑,这两个压缩算法都是比较有吸引力的算法。
- LZO和Snappy算法有更快的解压缩速度,如果更关注压缩、解压速度,它们都是不错的选择。 LZO和Snappy在压缩数据上的速度大致相当,但Snappy算法在解压速度上要较LZO更快。
- Hadoop的会将大文件分割成HDFS block(默认64MB)大小的splits分片,每个分片对应一个Mapper程序。在这几个压缩算法中 BZip2、LZO、Snappy压缩是可分割的,Gzip则不支持分割。
7、 常见压缩格式
压缩方式 |
压缩后大小 |
压缩速度 |
是否可以分隔 |
GZIP |
中 |
中 |
否 |
BZIP2 |
小 |
慢 |
是 |
LZO |
大 |
快 |
是 |
Snapp |
大 |
快 |
是 |
注: |
这里的可分隔是指:本地文件使用某种压缩算法进行压缩后传到hdfs上面,然后进行MapReduce计算,在mapper阶段是否支持对压缩后的文件进行split分隔,且分隔是否有效。 |
Hadoop编码/解码器方式,如下表所示
压缩格式 |
对应的编码/解码器 |
DEFAULT |
org.apache.hadoop.io.compress.DefaultCodec |
Gzip |
org.apache.hadoop.io.compress.GzipCodec |
Bzip |
org.apache.hadoop.io.compress.BZip2Codec |
DEFLATE |
org.apache.hadoop.io.compress.DeflateCodec |
Snappy |
org.apache.hadoop.io.compress.SnappyCodec(中间输出使用) |
Lzo |
org.apache.hadoop.io.compress.Lz4Codec(中间输出使用) |
8、对比结果
压缩前是74.1G,压缩后的文件目录大小
TextFile |
Sequence File |
RCFile |
ORC |
|
GZip |
23.8 G |
25.2 G |
22.5 G |
21.9 G |
Snappy |
39.5 G |
41.3 G |
39.1 G |
21.9 G |
BZIP |
17.9 G |
18.9 G |
18.7 G |
21.9 G |
LZO |
39.9 G |
41.8 G |
40.8 G |
21.9 G |
压缩后的文件名称
TextFile |
Sequence File |
RCFile |
ORC |
|
GZip |
*.gz |
000000_0 |
000000_1000 |
000000_0 |
Snappy |
*.snappy |
000000_0 |
000000_1 |
000000_0 |
BZIP |
*.bz2 |
000000_0 |
000000_1000 |
000000_0 |
LZO |
*.lz4 |
000000_2 |
000000_0 |
000000_0 |
导入数据消耗时间
TextFile |
Sequence File |
RCFile |
ORC |
|
GZip |
81.329s |
81.67s |
136.6s |
76.6s |
Snappy |
226s |
180s |
79.8s |
75s |
BZIP |
138.2s |
134s |
145.9s |
98.3s |
LZO |
231.8 |
234s |
86.1s |
248.1s |
查询速度
select count(1) from table_name
TextFile |
Sequence File |
RCFile |
ORC |
|
GZip |
46.2s |
50.4s |
44.3s |
38.3s |
Snappy |
46.3s |
54.3s |
42.2s |
40.3s |
BZIP |
114.3s |
110.3s |
40.3s |
38.2s |
LZO |
60.3s |
52.2s |
42.2s |
50.3s |
总结:
压缩比: |
BZip > Gzip > Snappy > LZO,但是对于ORC存储类型压缩比都是一样的 |
压缩时间: |
Gzip < BZip < Snappy < LZO,但是对应RCFile和ORC存储类型,都是Snappy压缩类型压缩的时间最短 |
数据统计时间: |
GZip < Snappy < LZO < Bzip,但是对应RCFile和ORC存储类型,都是BZip压缩类型查询时间最短 |
压缩类型推荐: |
1)BZip和Gzip都有很好的压缩比但是会带来更高的CPU消耗,如果是基于磁盘利用率和I/O,可以考虑着两种压缩算法
2)LZO和Snappy算法有更快的解压缩速度,如果关注压缩和解压缩速度,他们都是不错的选择。如果hive表的存储类型RCFile和ORC的时候,Snappy和LZO拥有相当的解压缩效率,但是在压缩方面Snappy较LZO更胜一筹
3)Hadoop会将大文件分隔成HDFS block大小的splits分片,每个分片对应一个Mapper程序。在这几个压缩算法中Bzip2、LZO、Snappy压缩是可以分隔的,Gzip则不支持分隔 |