提高Hadoop的mapreduce job效率笔记(3)

如果在mapreduce的作业中有类似这样的情况,那么job 就肯定是可以优化的:

Text 对象被用来处理非text的数据 或者复杂结构的数据

IntWritable orLongWritable objects are used when most output values tend to be significantly smaller than the maximum value.

当大多数的output中的value都比最大的value值要小的多的时候使用 IntWritable 或者 LongWritable对象。

当mapreduce的新手写mapreduce程序时,或是习惯了 Hadoop的streaming作业的使用方式,转而使用mapreduce来写程序时,常常会有人不正确的使用Text类,很多的时候,没有这个必要。虽然使用Text非常方便,但是,从数字类型转换成UTF8的字符串的效率是很低的,如果这样的操作很多,是会占用过多的cpu时间而导致作业效率降低。任何时候,当处理非文本数据(数字,浮点等类型),使用IntWritable或者FloatWritable的效率会高很多。

除了 Text的问题,二进制的writable 对象通常还会占用更少的存储空间 。由于磁盘IO和网络 的传输常常都是 mapreduce作业的瓶颈所在,这样做可以很大程度的提高job的性能,尤其是当job的规模很大的时候。当处理Integer数据时,同样有时是可以使用VIntWritable或者VLongWritable来提高性能。不仅可以减少cpu占用,也可以减少空间占用。例如,4,当序列化时会被序列化成1个byte,而10000序列化时会占用2个bytes。这种类似couters的值,序列化时的length就会很重要。当数据都是很小的数字,而只有一些是很大的时候,这样的效率节约是非常可观的。

如果hadoop中自带的Writable的各种类型不能满足需要,可以自己写一个。非常的简单,这样也可能会比直接用Text,然后解析来的高效。在写自己的Writable时,尝试提供一个RawComparator(可以从 hadoop的源码中找到类似的实现)。

同样,如果maprduce job是一系列job中的一个,可以在中间结果和中间job的output中都使用SequenceFile来保存中间结果,即使最后的输出需要使用文本化的数据。这样可以减少数据的中间结果,减低磁盘的 IO,并且节省网络传输。

测试对比:

对于example中的word count job,我们可以修改value中的数据类型从IntWritable为Text,在reduce中,用Integer.parseString(value.toString()) 来接收value信息。job的性能直接就降低了10%,整个job花了9分钟,并且每一个map都花费了36秒钟的时间,原先只需要33秒。由于 Integer的parse本身比较快,这样做并没有太大程度上的影响性能,而在通常情况下,不同的使用方式会产生2-3倍的性能差。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/2ff53daaf1561f3621c2eed25f4effcd.html