J'essaie de trouver un moyen efficace d'enregistrer le résultat de mon Spark Job en tant que fichier csv. J'utilise Spark avec Hadoop et jusqu'à présent) tous mes fichiers sont enregistrés sous part-00000
.
Des idées sur la façon de faire mon spark enregistrement dans un fichier avec un nom de fichier spécifié?
Étant donné que Spark utilise l'API Hadoop File System pour écrire des données dans des fichiers, cela est inévitable. Si vous le faites
rdd.saveAsTextFile("foo")
Il sera enregistré sous "foo/part-XXXXX
" Avec un fichier part- * chaque partition du RDD que vous essayez d'enregistrer. La raison pour laquelle chaque partition du RDD est écrite dans un fichier distinct est pour la tolérance aux pannes. Si la tâche d'écriture de la 3e partition (c'est-à-dire vers part-00002
) Échoue, Spark simplement réexécutez la tâche et écrasez le part-00002
Partiellement écrit/corrompu, sans Si elles ont toutes écrit dans le même fichier, il est beaucoup plus difficile de récupérer une seule tâche en cas d'échec.
Les fichiers part-XXXXX
Ne sont généralement pas un problème si vous allez les consommer à nouveau dans Spark/frameworks basés sur Hadoop parce qu'ils utilisent tous l'API HDFS, si vous leur demandez lire "foo", ils liront également tous les fichiers part-XXXXX
dans foo.
Je vous suggère de le faire de cette façon (exemple Java):
theRddToPrint.coalesce(1, true).saveAsTextFile(textFileName);
FileSystem fs = anyUtilClass.getHadoopFileSystem(rootFolder);
FileUtil.copyMerge(
fs, new Path(textFileName),
fs, new Path(textFileNameDestiny),
true, fs.getConf(), null);
Il existe une approche autre basée sur les opérations Hadoop FileSystem.
J'ai une idée, mais pas d'extrait de code prêt. En interne (comme son nom l'indique) Spark utilise le format de sortie Hadoop. (Ainsi que InputFormat
lors de la lecture depuis HDFS).
Dans le FileOutputFormat
du hadoop, il y a un membre protégé setOutputFormat
, que vous pouvez appeler à partir de la classe héritée pour définir un autre nom de base.
En utilisant Spark SQL, nous pouvons le faire dans une seule ligne
//implicits for magic functions like .toDf
import spark.implicits._
val df = Seq(
("first", 2.0),
("choose", 7.0),
("test", 1.5)
).toDF("name", "vals")
//write DataFrame/DataSet to external storage
df.write
.format("csv")
.save("csv/file/location")
Ce n'est pas vraiment une solution propre, mais dans un foreachRDD
(), vous pouvez essentiellement faire ce que vous voulez, également créer un nouveau fichier.
Dans ma solution, voici ce que je fais: j'enregistre la sortie sur HDFS (pour des raisons de tolérance aux pannes), et à l'intérieur d'un foreachRDD
je crée également un fichier TSV avec des statistiques dans un dossier local.
Je pense que vous pourriez probablement faire de même si c'est ce dont vous avez besoin.
http://spark.Apache.org/docs/0.9.1/streaming-programming-guide.html#output-operations