一般而言,saveAsTextFile會按照執行task的多少生成多少個文件,比如part-00000一直到part-0000n,n自然就是task的個數,亦即是最后的stage的分區數。那么有沒有辦法最后只生成一個文件,而不是成百上千個文件了?答案自然是有辦法。
在RDD上調用coalesce(1,true).saveAsTextFile()
,意味着做完計算之后將數據匯集到一個分區,然后再執行保存的動作,顯然,一個分區,Spark自然只起一個task來執行保存的動作,也就只有一個文件產生了。又或者,可以調用repartition(1),它其實是coalesce的一個包裝,默認第二個參數為true。
事情最終就這么簡單嗎?顯然不是。你雖然可以這么做,但代價是巨大的。因為Spark面對的是大量的數據,並且是並行執行的,如果強行要求最后只有一個分區,必然導致大量的磁盤IO和網絡IO產生,並且最終執行reduce操作的節點的內存也會承受很大考驗。Spark程序會很慢,甚至死掉。
這往往是初學Spark的一個思維陷阱,需要改變原先那種單線程單節點的思維,對程序的理解要轉變多多個節點多個進程中去,需要熟悉多節點集群自然產生多個文件這種模式。
此外,saveAsTextFile要求保存的目錄之前是沒有的,否則會報錯。所以,最好程序中保存前先判斷一下目錄是否存在。