0%

数据压缩

数据压缩

压缩可以减少HDFS读写字节数,提高网络带宽和磁盘空间效率,所以压缩非常重要,可以在MapReduce的任意阶段进行压缩

压缩减少了磁盘IO,但是增加了CPU的运算负担,所以要采用下述原则

  • 运算密集型的job,少用压缩
  • IO密集型的job,多用压缩

压缩方式

压缩格式 hadoop自带? 算法 文件扩展名 是否可切分 换成压缩格式后,原来的程序是否需要修改 对应的编码/解码器 压缩率 压缩速度
DEFLATE 是,直接使用 DEFLATE .deflate 和文本处理一样,不需要修改 org.apache.hadoop.
io.compress.DefaultCodec
Gzip 是,直接使用 DEFLATE .gz 和文本处理一样,不需要修改 org.apache.hadoop.
io.compress.GzipCodec
较高 压缩/解压缩较快
bzip2 是,直接使用 bzip2 .bz2 和文本处理一样,不需要修改 org.apache.hadoop.
io.compress.BZip2Codec
较高,比Gzip高 压缩/解压缩慢
LZO 否,需要安装 LZO .lzo 需要建索引,还需要指定输入格式 com.hadoop.compression
.lzo.LzopCodec
较高,比Gzip低 压缩/解压缩较快
Snappy 否,需要安装 Snappy .snappy 和文本处理一样,不需要修改 org.apache.hadoop.
io.compress.SnappyCodec
比Gzip低 高速压缩/解压缩

压缩配置

在core-site.xml中

1
2
3
4
5
6
7
<!-- 配置使用的编解码器 -->
<property>
<name>io.compression.codecs</name>
<value>org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec</value>
</property>


mapred-site.xml中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

<!-- map输出是否压缩 默认false -->
<property>
<name>mapreduce.map.output.compress</name>
<value>true</value>
</property>

<!-- map输出使用的压缩格式 默认org.apache.hadoop.io.compress.DefaultCodec -->
<property>
<name>mapreduce.map.output.compress.codec</name>
<value>org.apache.hadoop.io.compress.DefaultCodec</value>
</property>

<!-- reduce输出是否压缩 -->
<property>
<name>mapreduce.output.fileoutputformat.compress</name>
<value>true</value>
</property>

<!-- 压缩的类型,有NONE、RECORD和BLOCK 默认是RECORD -->
<property>
<name>mapreduce.output.fileoutputformat.compress.type</name>
<value>RECORD</value>
</property>
<!-- 压缩格式,默认org.apache.hadoop.io.compress.DefaultCodec -->
<property>
<name>mapreduce.output.fileoutputformat.compress.codec</name>
<value>org.apache.hadoop.io.compress.DefaultCodec</value>
</property>

压缩位置

输入端压缩

在有大量数据并计划重复处理的情况下,应该考虑对输入进行压缩(hadoop在自动检查文件扩展名,并使用扩展名匹配,自动进行压缩/解压缩)

Mapper输出采用压缩

Map任务输出的中间数据量很大时,可以在此阶段采用压缩,可以改善内部数据Shuffle过程

Reducer输出采用压缩

此阶段采用压缩可以减少要存储的数据量,减少磁盘空间占用

实现编码示例

1
2
3
4
5
6
// 获取压缩/解压缩方式   一般使用反射,不是使用直接new的方式
DefaultCodec codec = new DefaultCodec();
// 把压缩文件的输入流放入可以获取到该文件解压缩之后的输入流
CompressionInputStream compressionInputStream = codec.createInputStream(inputstream);
// 把输出流放入可以获取到压缩之后的输出流
CompressionOutputStream compressionOutputStream = codec.createOutputStream(outputStream);