有个MR Job,输入数据大小几G,输入大小估计几十T(未压缩)。输出量太大,为空间方面考虑决定使用压缩。map的输出与Job的输入一样大小,优化幅度不大,暂时不考虑map输出的压缩,着重于Reduce输出的压缩。《Hadoop权威指南》中介绍了几种压缩格式,因为此Job的输出还要作为下一个MR的输入,故:
1. 第一次选了《权威指南》中介绍的支持切分的bzip2格式,输出格式为Sequence File。结果:速度贼慢,比不压缩的还慢。可以断定在压缩上面花费过多时间。
2. bzip2压缩只能放弃,但又不甘心无压缩输出。搜索了些资料(http://blog.sina.com.cn/s/blog_62a9902f0100zqbb.html)后决定采用lzo压缩。
conf.setBoolean("mapred.output.compress", true); conf.setClass("mapred.output.compression.codec", LzoCodec.class, CompressionCodec.class);
//注意到底该用LzoCodec还是LzopCodec,另一篇文章单独讲这个
另外为增强效果,
job.setOutputFormatClass(SequenceFileOutputFormat.class);
conf.set("mapred.output.compression.type", "BLOCK");
结果运行速度大幅提升。
分析:这个Job中的Reducer为IO密集型,用压缩来减少输出量可以提高运行速度,但不宜使用太耗时的压缩算法。如果兼顾时间和空间,lzo是个不错的选择。
关于lzo压缩文件作为MR的输入:
1. 如果能够拥有一种压缩算法,既能够被分块、并行的处理,速度也非常的快,那就非常的理想。这种方式就是lzo。 lzo的压缩文件是由许多的小的blocks组成(约256K),使的Hadoop的job可以根据block的划分来split job。不仅如此,lzo在设计时就考虑到了效率问题,
它的解压速度是gzip的两倍,这就让它能够节省很多的磁盘读写,它的压缩比的不如gzip,大约压缩出来的文件比gzip压缩的大一半,但是这样仍然比没有经
过压缩的文件要节省20%-50%的存储空间,这样就可以在效率上大大的提高job执行的速度。
2. 在hadoop中使用lzo的压缩算法可以减小数据的大小和数据的磁盘读写时间,不仅如此,lzo是基于block分块的,这样他就允许数据被分解成chunk,并行
的被hadoop处理。这样的特点,就可以让lzo在hadoop上成为一种非常好用的压缩格式。
lzo本身不是splitable的,所以当数据为text格式时,用lzo压缩出来的数据当做job的输入是一个文件作为一个map。但是sequencefile本身是分块的,
所以sequence file格式的文件,再配上lzo的压缩格式,就可实现lzo文件方式的splitable。