MR-4.MapReduce使用压缩

来源:互联网 发布:用友u8数据库不符合 编辑:程序博客网 时间:2024/05/16 14:24

MapReduce处理数据时,需要考虑压缩格式是否支持分片是很重要的。考虑存储在HDFS重的未压缩文件,其大小为1GB。HDFS块大小为128M,该文件在HDFS存储分成8块存,作为MapReduce输入将创建8个分片(split,也称为“分块”)。每个分片都被作为一个独立的MapTask的输入单独进行处理。

 

假设,一个压缩后1GB的gzip格式的文件。HDFS块大小为128M,在HDFS存储8个分块。然而针对每一block创建一个分片是没有用的,因为不能从gzip格式数据流中的任意一点开始读取。因此gzip格式不支持分片(分割)。

 

对于格式为gzip格式的1GB的文件,随被分成8块存储,但是MapReduce对gzip格式文件不分片,也就是说8块存储的数据通过一个MapTask处理,大都不是map的本地数据。因为MapTask少,从而导致运行时间变长。

 

对于gzip2格式压缩1GB文件,因为它支持分片,故可以多个MapTask处理,性能较高。

 

思考问题:实际项目应用中应该使用哪种压缩格式呢?

考虑Hadoop应用处理的数据集比较大,因此需要借助压缩。按照效率从高到低排列的

(1)       使用容器格式文件,例如:顺序文件、RCFile、Avro数据格式支持压缩和切分文件。另外在配合使用一些快速压缩工具,例如:LZO、LZ4或者Snappy.

(2)       使用支持切分压缩格式,例如gzip2

(3)       在应用中将文件切分成块,对每块进行任意格式压缩。这种情况确保压缩后的数据库接近HDFS块大小。

(4)       存储未压缩文件,以原始文件存储。

总之,对于大文件来说,不要使用不支持切分整个文件的压缩格式,因为失去数据本地特性,进而造成MapReduce应用效率低下。



编写MapReduce程序时候,有时候需要在程序中对map任务的输出结果或者MapReduce作业进行压缩。

(1)对map任务输出进行压缩

由于map任务的输出需要写到磁盘并通过网络传输到reducer节点,所以如果使用LZO、LZ4或者Snappy这样的快速压缩方式和,是可以提升性能的。启用map任务中间节点的方法:

// 对map任务输出进行压缩

conf.setBoolean("mapreduce.map.output.compress.codec",true);

conf.setClass("mapreduce.map.output.compress", GzipCodec.class, CompressionCodec.class);

 

(2)Map作业中使用压缩

// 对作业输出结果进行压缩

FileOutputFormat.setCompressOutput(job,true);

FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);

 

如果输出生成顺序文件(sequence file),可以通过以下设置来完成

job.setOutputFormatClass(SequenceFileOutputFormat.class);

SequenceFileOutputFormat.setCompressOutput(job, true);

SequenceFileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);

SequenceFileOutputFormat.setOutputCompressionType(job, CompressionType.BLOCK);

注意:默认情况下是RECORD,即针对每条记录进行压缩。如果改成BLOCK,将针对一组记录进行压缩。这也是推荐的压缩策略,因此它的压缩效率更高。


0 0
原创粉丝点击