原文地址:
http://www.cnblogs.com/029zz010buct/p/4685173.html
一般而言,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要求保存的目錄之前是沒有的,否則會報錯。所以,最好程序中保存前先判斷一下目錄是否存在。
================================================================================================
原鏈接:
http://blog.csdn.net/power0405hf/article/details/50596233
當我運行完一個Spark程序想把結果保存為saveAsTextFile
,
結果使用Hadoop fs -ls /output
后發現里面有一系列的part,好幾千個。
原因:
運行Spark的時候把數據分成了很多份(partition),每個partition都把自己的數據保存成partxxx文件形式。
如果想保存為一份的話,就要:
先collect
或者
data.coalesce(1,true).saveAsTextFile()
也或者
data.repartition(1).saveAsTextFile( ) //You can also use repartition(1), which is just a wrapper for coalesce() with the suffle argument set to true.
data.repartition(1).saveAsTextFile( “HDFS://OUTPUT”)
但是如果你的數據很大,難以在單機內存上裝下,以上操作可能會造成單機內存不足。
原因在於以上操作都是講分布在各個機器上的數據匯總到單機,然后再保存到磁盤(HDFS)上。
以上操作將各個機器上的RDD partition 合並到單一主機后再讀入磁盤。
以下給出更安全的操作,即采用HDFS磁盤合並操作。
如果已經存了很多個part:
可以把大文件夾getmerge:
把HDFS 上的多個文件 合並成一個 本地文件:
hadoop fs -getmerge /hdfs/output /local/file.txt
也可以:
hadoop fs -cat /hdfs/output/part-r-* > /local/file.txt