最近需要在hadoop上存储较多的用户历史数据,占用磁盘空间较大。整理下看到的Hadoop压缩资料,期望对同样有此需求的同学有所帮助。


hadoop对每个压缩格式的支持,详细见下表:

hdfs dfs 解压缩 hdfs压缩比_hadoop

可分割性可以理解为能否在每块的开始位置定位到下一块的起始位置。

hadoop下各种压缩算法的压缩比,压缩时间,解压时间见下表:


压缩算法

原始文件大小

压缩后的文件大小

压缩速度

解压缩速度

gzip

8.3GB

1.8GB

17.5MB/s

58MB/s

bzip2

8.3GB

1.1GB

2.4MB/s

9.5MB/s

LZO-bset

8.3GB

2GB

4MB/s

60.6MB/s

LZO

8.3GB

2.9GB

49.3MB/S

74.6MB/s







lzo的压缩率不高,但是压缩、解压速度都比较高。


hadoop各种压缩算法的优缺点简述:

在考虑如何压缩那些将由MapReduce处理的数据时,考虑压缩格式是否支持分割是很重要的。

考虑存储在HDFS中的未压缩的文件,其大小为1GB,HDFS的块大小为64MB,所以该文件将被存储为16块。

将此文件用作输入的MapReduce作业会创建1个输入分片(split ,也称为“分块”。对于block,我们统一称为“块”。)每个分片都被作为一个独立map任务的输入单独进行处理。

现在假设。该文件是一个gzip格式的压缩文件,压缩后的大小为1GB。和前面一样,HDFS将此文件存储为16块。然而,针对每一块创建一个分块是没有用的,因为不可能从gzip数据流中的任意点开始读取,map任务也不可能独立于其他分块只读取一个分块中的数据。gzip格式使用DEFLATE来存储压缩过的数据,DEFLATE将数据作为一系列压缩过的块进行存储。问题是,每块的开始没有指定用户在数据流中任意点定位到下一个块的起始位置,而是其自身与数据流同步。因此,gzip不支持分割(块)机制。


如何在map-reduce端使用压缩:

(1)输入文件的压缩

map-reduce的输入,是不需要指定格式的。程序会根据后缀名来判断压缩格式。

(2)输出文件的压缩

如果要压缩MapReduce作业的输出,请在作业配置文件中将mapred.output.compress属性设置为true。

将mapred.output.compression.codec属性设置为自己打算使用的压缩编码/解码器的类名。

如果为输出使用了一系列文件,可以设置mapred.output.compression.type属性来控制压缩类型,默认为RECORD,它压缩单独的记录。

将它改为BLOCK,则可以压缩一组记录。由于它有更好的压缩比,所以推荐使用。


mahout中的例子(BtJob),用默认的压缩方式,对块进行压缩。

    FileOutputFormat.setOutputCompressorClass(job, DefaultCodec.class);
    SequenceFileOutputFormat.setOutputCompressionType(job, CompressionType.BLOCK);


参考资料:

Hadoop在MapReduce中使用压缩详解 http://developer.51cto.com/art/201204/331337.htm

Hadoop实战之初级IO http://sishuok.com/forum/blogPost/list/5460.html

Hadoop 的解压与压缩