對於那些更大的數據集工作並且仍願意從中獲利火花的平行性,rdd.coalesce(1).saveAsTextFile("path")
不是解決方案。整個管道(從最後的火花動作到存儲)將在1個執行器上執行。
可以代替第一執行對執行者的任何數量的管道,並使用saveAsTextFile
(這將產生輸出多個文件)然後只使用apache FileSystem
API合併所有這些文件。
以下方法給出RDD存儲和路徑在哪裏存儲它:
import org.apache.spark.rdd.RDD
import org.apache.hadoop.fs.{FileSystem, FileUtil, Path}
import org.apache.hadoop.conf.Configuration
def saveAsSingleTextFile(
outputRDD: RDD[String],
outputFile: String
): Unit = {
// Classic saveAsTextFile in a temporary folder:
outputRDD.saveAsTextFile(outputFile + ".tmp")
// The facility allowing file manipulations on hdfs:
val hdfs = FileSystem.get(new Configuration())
// Merge the folder into a single file:
FileUtil.copyMerge(
hdfs,
new Path(outputFile + ".tmp"),
hdfs,
new Path(outputFile),
true,
new Configuration(),
null)
// And we delete the intermediate folder:
hdfs.delete(new Path(outputFile + ".tmp"), true)
}
這樣的處理仍然分佈和合流部被之後完成的,這限制了在性能上的損失。
在獎金中,您可以提供輸出文件的確切名稱,與生成文件my/path/part-00000的rdd.coalesce(1).saveAsTextFile(「my/path」)相反。
如果文件很大,在大數據中只使用一個文件通常是不好的做法。 – samthebest
如果輸出結果是排序文件,那麼最佳做法是什麼?把它保存爲一個文件集合,並使許多輸出文件名稱成爲某種索引(即第一個文件名稱爲「aa」,中間的文件名稱會像「fg」,最後一個是「zzy」)? – Rdesmond
通常情況下,重火花工作只會產生非常小的輸出(彙總,kpis,popularities,...),這是在hdfs上產生的,但最有可能是後者在與大數據無關的應用程序中使用。在這種情況下,更清潔,更容易擁有一個有名的單一文件傳輸和消費。 –