Nous exécutons spark 2.3.0 on AWW EMR
. Le DataFrame
"df
" suivant n'est pas vide et de taille modeste:
scala> df.count
res0: Long = 4067
Le code suivant fonctionne très bien pour écrire df
dans hdfs
:
scala> val hdf = spark.read.parquet("/tmp/topVendors")
hdf: org.Apache.spark.sql.DataFrame = [displayName: string, cnt: bigint]
scala> hdf.count
res4: Long = 4067
Cependant, l'utilisation du même code pour écrire dans un fichier local parquet
ou csv
aboutit à des résultats vides:
df.repartition(1).write.mode("overwrite").parquet("file:///tmp/topVendors")
scala> val locdf = spark.read.parquet("file:///tmp/topVendors")
org.Apache.spark.sql.AnalysisException: Unable to infer schema for Parquet. It must be specified manually.;
at org.Apache.spark.sql.execution.datasources.DataSource$$anonfun$9.apply(DataSource.scala:207)
at org.Apache.spark.sql.execution.datasources.DataSource$$anonfun$9.apply(DataSource.scala:207)
at scala.Option.getOrElse(Option.scala:121)
Nous pouvons voir pourquoi il échoue:
ls -l /tmp/topVendors
total 0
-rw-r--r-- 1 hadoop hadoop 0 Jul 30 22:38 _SUCCESS
Il y a donc non fichier parquet en cours d'écriture.
J'ai essayé cela peut-être vingt fois et pour csv
et parquet
et sur deux serveurs EMR
différents: ce même comportement se manifeste dans tous les cas.
S'agit-il d'un bogue spécifique à EMR
? Un plus général EC2
punaise? Autre chose? Ce code fonctionne sur spark
sur macos
.
Au cas où cela compte - voici les informations de version:
Release label:emr-5.13.0
Hadoop distribution:Amazon 2.8.3
Applications:Spark 2.3.0, Hive 2.3.2, Zeppelin 0.7.3
Ce n'est pas un bug et c'est le comportement attendu. Spark ne prend pas vraiment en charge les écritures sur le stockage non distribué (il fonctionnera en mode local
, simplement parce que vous avez un système de fichiers partagé).
Le chemin local n'est pas interprété (uniquement) comme un chemin sur le pilote (cela nécessiterait la collecte des données) mais un chemin local sur chaque exécuteur. Par conséquent, chaque exécuteur écrit son propre morceau dans son propre système de fichiers local.
Non seulement la sortie n'est pas lisible (pour charger les données, chaque exécuteur et le pilote doivent voir le même état du système de fichiers), mais en fonction de l'algorithme de validation, il se peut qu'il ne soit même pas finalisé (déplacement depuis le répertoire temporaire).
Cette erreur se produit généralement lorsque vous essayez de lire un répertoire vide en tant que parquet. Vous pouvez vérifier 1. si le DataFrame est vide avec result.rdd.isEmpty () avant de l'écrire. 2. Vérifiez si le chemin que vous donnez est correct
Aussi dans quel mode vous exécutez votre application? Essayez de l'exécuter en mode client si vous exécutez en mode cluster.