場景:
??讀取2g大小的文件,做一些簡單的處理并將保存結(jié)果,為了方便的下載我將結(jié)果數(shù)據(jù)分成2個(gè)分區(qū),分區(qū)方式是.coalesce(2).saveAsTestFile(path)。
問題:
??Spark任務(wù)運(yùn)行起來很慢,一個(gè)2g的文件居然跑了2.3個(gè)小時(shí)才跑完。為了充分利用并行化,我又在讀file的時(shí)候?qū)?shù)據(jù)進(jìn)行了分區(qū) —— sc.textFile(path, 20),但是依然不起作用。
查明原因:
??查閱了相關(guān)資料后終于明白問題根源了,就是coalesce惹的禍。首先講一下coalesce和reparation的區(qū)別,coalesce和repartition都是對RDD進(jìn)行分區(qū),不過coalesce沒有進(jìn)行shuffle操作,而repartition進(jìn)行了shuffle操作。講道理不進(jìn)行shuffle操作的coalesce應(yīng)該會(huì)更快,但是為什么反而很慢呢?原因就是DAGScheduler創(chuàng)建Task的數(shù)量取決于Stage的最后一個(gè)RDD的分區(qū)數(shù)(引用資料)。coalesce沒有shuffle,整個(gè)過程都屬于一個(gè)階段,因此最終該過程的task數(shù)量是2,盡管我在最開始分了20個(gè)分區(qū),沒用!系統(tǒng)只會(huì)分給我2個(gè)task。但是repartition就不一樣了,因?yàn)橛衧huffle操作,整個(gè)過程被repartition一分為二個(gè)stage,兩個(gè)stage互不干擾。stage1是數(shù)據(jù)讀入和處理,因?yàn)槲曳至?0個(gè)分區(qū),所以系統(tǒng)就會(huì)給我20個(gè)task,stage2是數(shù)據(jù)保存,我將最終分區(qū)數(shù)定為2,那么該階段的task就是2。不過沒關(guān)系,stage1的task從2變成了20,整個(gè)過程還是加快了。
效果對比:
使用coalesce的話,處理一個(gè)2g的文件用了2.3h
使用repartition的話,處理一個(gè)2g的文件用了20min