web-dev-qa-db-fra.com

L'enregistrement de la trame de données dans le système de fichiers local entraîne des résultats vides

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
11
javadba

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).

7
user6910411

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.

0
geekay2015