MapReduce输入输出类型、格式及实例

输入格式

1、输入分片与记录 2、文件输入 3、文本输入 4、二进制输入 5、多文件输入 6、数据库格式输入

1、输入分片与记录

1、JobClient通过指定的输入文件的格式来生成数据分片InputSplit。 2、一个分片不是数据本身,而是可分片数据的引用。 3、InputFormat接口负责生成分片。

InputFormat 负责处理MR的输入部分,有三个作用: 验证作业的输入是否规范。 把输入文件切分成InputSplit。 提供RecordReader 的实现类,把InputSplit读到Mapper中进行处理。

2、文件输入

抽象类:FilelnputFormat 1、FilelnputFormat是所有使用文件作为数据源的InputFormat实现的基类。 2、FilelnputFormat输入数据格式的分片大小由数据块大小决定。

FileInputFormat保存作为job输入的所有文件,并实现了对输入文件计算splits的方法。至于获得记录的方法是有不同的子类——TextInputFormat进行实现的。

package org.apache.hadoop.mapreduce.lib.input;FileInputFormat<K, V> extends InputFormat<K, V> { (long blockSize, long minSize,long maxSize) {return Math.max(minSize, Math.min(maxSize, blockSize)); } /*Generate the list of files and make them into FileSplits.*/ public List<InputSplit> getSplits(JobContext job) throws IOException {long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job));long maxSize = getMaxSplitSize(job);……long blockSize = file.getBlockSize();long splitSize = computeSplitSize(blockSize, minSize, maxSize);…… } (JobContext job) {return job.getConfiguration().getLong(SPLIT_MINSIZE, 1L); } (JobContext context) {return context.getConfiguration().getLong(SPLIT_MAXSIZE,Long.MAX_VALUE); }//是否分片/*Is the given filename splitable? Usually, true, but if the file is stream compressed, it will not be.<code>FileInputFormat</code> implementations can override this and return <code>false</code> to ensure that individual input files are never split-up so that {@link Mapper}s process entire files.*/protected boolean isSplitable(JobContext context, Path filename) {return true;//默认需要分片 }}自定义输入格式

如果我们不需要分片,那我们就需要对isSplitable方法进行重写 1、继承FileInputFormat基类。 2、重写里面的getSplits(JobContext context)方法。 3、重写createRecordReader(InputSplit split,TaskAttemptContext context)方法。 详细例子:

InputSplit

在执行mapreduce之前,原始数据被分割成若干split,每个split作为一个map任务的输入,在map执行过程中split会被分解成一个个记录(key-value对), map会依次处理每一个记录。 FileInputFormat只划分比HDFS block大的文件,所以FileInputFormat划分 的结果是这个文件或者是这个文件中的一部分。 如果一个文件的大小比block小,将不会被划分,这也是Hadoop处理大文件 的效率要比处理很多小文件的效率高的原因。 当Hadoop处理很多小文件(文件大小小于hdfs block大小)的时候,由于 FileInputFormat不会对小文件进行划分,所以每一个小文件都会被当做一个split并分配一个map任务,导致效率底下。 例如:一个1G的文件,会被划分成16个64MB的split,并分配16个map任务处 理,而10000个100kb的文件会被10000个map任务处理。

Map任务的数量?

一个InputSplit对应一个Map task。 InputSplit的大小是由Math.max(minSize,Math.min(maxSize, blockSize))决定。 单节点一般10-100个map task。map task执行时长不建议低于1 分钟,,否 则效率低。

抽象类:CombineFilelnputFormat 1、可以使用CombineFilelnputFormat来合并小文件。

2、因为CombineFilelnputFormat是一个抽象类,使用的时候需要创建一个 CombineFilelnputFormat的实体类,并且实现getRecordReader()的方法。

3、避免文件分法的方法: A、数据块大小尽可能大,这样使文件的大小小于数据块的大小,就不用进行分片。(这种方式不太友好) B、继承FilelnputFormat,并且重写isSplitable()方法。

job.setInputFormatClass(CombineTextInputFormat.class);

Hadoop2.6.0 CombineTextInputFormat源码:

package org.apache.hadoop.mapreduce.lib.input; CombineFileInputFormat<LongWritable,Text> { public RecordReader<LongWritable,Text> createRecordReader(InputSplit split,TaskAttemptContext context) throws IOException {return new CombineFileRecordReader<LongWritable,Text>((CombineFileSplit)split, context, TextRecordReaderWrapper.class); } TextRecordReaderWrapper(CombineFileSplit split,TaskAttemptContext context, Integer idx)throws IOException, InterruptedException {super(new TextInputFormat(), split, context, idx);} }}3、文本输入

类名:TextlnputFormat 1、TextlnputFormat是默认的lnputFormat,每一行数据就是一条记录。

2、TextlnputFormat的key是LongWritable类型的,存储该行在整个文件的偏移量,value是每行的数据内容,Text类型。

3、输入分片与HDFS数据块关系:TextlnputFormat每一条记录就是一行,很有可能某一行跨数据块存放。默认以\n或回车键作为一行记录。

4、TextInputFormat继承了FileInputFormat。

天不负;卧薪尝胆,三千越甲可吞吴。

MapReduce输入输出类型、格式及实例

相关文章:

你感兴趣的文章:

标签云: