场景:
读取2g大小的文件,做一些简单的处理并将保存结果,为了方便的下载我将结果数据分成2个分区,分区方式是.coalesce(2).saveAsTestFile(path)。
问题:
Spark任务运行起来很慢,一个2g的文件居然跑了2.3个小时才跑完。为了充分利用并行化,我又在读file的时候对数据进行了分区 —— sc.textFile(path, 20),但是依然不起作用。
查明原因:
查阅了相关资料后终于明白问题根源了,就是coalesce惹的祸。首先讲一下coalesce和reparation的区别,coalesce和repartition都是对RDD进行分区,不过coalesce没有进行shuffle操作,而repartition进行了shuffle操作。讲道理不进行shuffle操作的coalesce应该会更快,但是为什么反而很慢呢?原因就是DAGScheduler创建Task的数量取决于Stage的最后一个RDD的分区数(引用资料)。coalesce没有shuffle,整个过程都属于一个阶段,因此最终该过程的task数量是2,尽管我在最开始分了20个分区,没用!系统只会分给我2个task。但是repartition就不一样了,因为有shuffle操作,整个过程被repartition一分为二个stage,两个stage互不干扰。stage1是数据读入和处理,因为我分了20个分区,所以系统就会给我20个task,stage2是数据保存,我将最终分区数定为2,那么该阶段的task就是2。不过没关系,stage1的task从2变成了20,整个过程还是加快了。
效果对比:
使用coalesce的话,处理一个2g的文件用了2.3h
使用repartition的话,处理一个2g的文件用了20min
网友评论