1 压缩格式
运算密集型的job,少用压缩,IO密集型的job,多用压缩。
压缩格式 | hadoop自带 | 算法 | 文件拓展名 | 是否可以切分 | 换成压缩格式后,原 来的程序是否需要修改 |
---|---|---|---|---|---|
DEFAULT | 是,直接使用 | DEFAULT | .deflate | 否 | 和文本处理一样,不需要修改 |
Gzip | 是,直接使用 | DEFAULT | .gz | 否 | 和文本处理一样,不需要修改 |
bzip2 | 是,直接使用 | bzip2 | .bz2 | 是 | 和文本处理一样,不需要修改 |
LZO | 否,需要安装 | LZO | .lzo | 是 | 需要建立索引,还需要指定输入格式 |
Snappy | 否,需要安装 | Snappy | .snappy | 否 | 和文本处理一样,不需要修改 |
为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器,如下表所示
压缩格式 | 对应的编码/解码器 |
---|---|
DEFLATE | org.apache.hadoop.io.compress.DefaultCodec |
gzip | org.apache.hadoop.io.compress.GzipCodec |
bzip2 | org.apache.hadoop.io.compress.BZip2Codec |
LZO | com.hadoop.compression.lzo.LzopCodec |
Snappy | org.apache.hadoop.io.compress.SnappyCodec |
2 压缩方式
压缩格式 | 压缩率 | 压缩速度 | 是否支持split | 应用场景 |
---|---|---|---|---|
Gzip | 比较高 | 比较快 | 否 | 当每个文件压缩之后在130M以内的(1个块大小内), 都可以考虑用gzip |
Bzip2 | 很高 | 慢 | 是 | 对速度要求不高,但需要较高的压缩率的时候,可以作为 MR作业的输出格式; 输出之后的数据比较大,处理之后的数据需要压缩存档减少 磁盘空间并且以后数据用得比较少的情况; 对单个很大的文本文件想压缩减少存储空间,同时又需要支持 split,而且兼容之前的应用程序(即应用程序不需要修改)。 |
Lzo | 比gzip低 | 是 | hadoop中较为流行的压缩方式 | |
Snappy | 否 | 作为Map到Reduce的中间数据的压缩格式; 作为一个MR作业的输出和另外一个MR作业的输入。 |
注:通常来讲,压缩率和压缩速度成反比,压缩速率高势必会导致压缩速度变慢。反之亦然。
3 压缩位置
压缩可以在mapreduce的所有过程使用。
4 压缩参数配置
参数 | 默认值 | 阶段 | 使用建议 |
---|---|---|---|
io.compression.codecs (在 core-site.xml 中配置) | org.apache.hadoop.io.compress.DefaultCodec org.apache.hadoop.io.compress.GzipCodec org.apache.hadoop.io.compress.BZip2Codec | 输入压缩 | Hadoop 使用文件扩展名判断是否支持某种编解码器 |
mapreduce.map.output.compress 在 mapred-site.xml中配置) | false | mapper 输出 | 这个参数设为true 启用压缩 |
mapreduce.map.output.compress.codec ( 在mapred-site.xml 中配置) | org.apache.hadoop.io.compress.DefaultCodec | mapper 输出 | 使 用LZO 或snappy编解码器在此阶段压缩数据 |
mapreduce.output.fileoutputformat.compress ( 在mapred-site.xml 中配置) | false | reducer 输出 | 这个参数设为true 启用压缩 |
mapreduce.output.fileoutputformat.compress.codec (在mapred-site.xml 中配置) | org.apache.hadoop.io.compress.DefaultCodec | reducer 输出 | 使用标准工具或者编解 码器,如gzip 和bzip2 |
mapreduce.output.fileoutputformat.compress.type (在mapred-site.xml 中配置) | RECORD | reducer 输出 | SequenceFile输出使用的压缩 类型 :NONE和BLOCK |
5 代码实例
5.1 解压缩操作
public class TestCompress {
public static void main(String[] args) throws Exception {
//1.测试压缩
//compress("e:/hello.txt","org.apache.hadoop.io.compress.BZip2Codec");
//compress("e:/hello.txt","org.apache.hadoop.io.compress.GzipCodec");
compress("e:/hello.txt","org.apache.hadoop.io.compress.DefaultCodec");
//2.测试解压
decompress("e:/hello.txt.deflate");
}
//测试压缩
private static void compress(String filename, String method) throws Exception {
// 1.获取输入流
//将文件转化为输入流
FileInputStream fis=new FileInputStream(new File(filename));
//获取压缩的格式
Class classname=Class.forName(method);
//设置压缩编解码
CompressionCodec codec=(CompressionCodec)ReflectionUtils.newInstance(classname, new Configuration());
// 2.获取输出流
//创建输出流
FileOutputStream fos=new FileOutputStream(new File(filename+codec.getDefaultExtension()));
//创建压缩后的输出流
CompressionOutputStream cos=codec.createOutputStream(fos);
// 3.流的对转
IOUtils.copyBytes(fis, cos, 1024*1024*5, false);
// 4.关闭资源
fis.close();
cos.close();
fos.close();
}
//测试解压
private static void decompress(String filename) throws Exception, IOException{
// 0.校验能不能解压
CompressionCodecFactory factory=new CompressionCodecFactory(new Configuration());
CompressionCodec codec=factory.getCodec(new Path(filename));
if(codec==null){
System.out.println("不支持该解码器"+filename);
return;
}
// 1.获取输入流
CompressionInputStream cis=codec.createInputStream(new FileInputStream(new File(filename)));
// 2.获取输出流
FileOutputStream fos=new FileOutputStream(new File(filename+"111"));
// 3.流的对转
IOUtils.copyBytes(cis, fos, 1024*1024*5, false);
// 4.关闭资源
cis.close();
fos.close();
}
}
5.2 以WordCount案例为例。
public class WordcountDriver {
public static void main(String[] args) throws Exception {
args=new String[]{"e:/input/inputword","e:/output/outputword2"};
//1.获取配置信息,job对象实例
Configuration configuration= new Configuration();
//开启map端输出压缩
configuration.setBoolean("mapreduce.map.output.compress",true);
//设置map端输出压缩方式
configuration.setClass("mapreduce.map.output.compress.codec",BZip2Codec.class,CompressionCodec.class);
Job job=Job.getInstance(configuration);
//2指定本程序的jar包所在的本地路径
//job.setJar("");
job.setJarByClass(WordcountDriver.class);
//3 指定本业务job要使用的自定义的mapper/Reducer业务类
job.setMapperClass(WordcountMapper.class);
job.setReducerClass(WordcountReducer.class);
//4指定mapper输出数据可kv类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//5设置最终输出数据类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//6设置数据输入和输出文件的路径
FileInputFormat.setInputPaths(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
//设置reduce端输出压缩开启
FileOutputFormat.setCompressOutput(job,true);
//设置压缩的方式
//FileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class);
//FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
FileOutputFormat.setOutputCompressorClass(job, DefaultCodec.class);
//7提交代码
//job.submit();
boolean result=job.waitForCompletion(true);
System.exit(result ? 0:1);
}
}