J'ai deux fichiers de parquet, l'un contenant un champ entier myField
et un autre contenant un champ double myField
. Lorsque vous essayez de lire les deux fichiers en même temps
val basePath = "/path/to/file/"
val fileWithInt = basePath + "intFile.snappy.parquet"
val fileWithDouble = basePath + "doubleFile.snappy.parquet"
val result = spark.sqlContext.read.option("mergeSchema", true).option("basePath", basePath).parquet(Seq(fileWithInt, fileWithDouble): _*).select("myField")
Je reçois l'erreur suivante
Caused by: org.Apache.spark.SparkException: Failed to merge fields 'myField' and 'myField'. Failed to merge incompatible data types IntegerType and DoubleType
En passant un schéma explicite
val schema = StructType(Seq(new StructField("myField", IntegerType)))
val result = spark.sqlContext.read.schema(schema).option("mergeSchema", true).option("basePath", basePath).parquet(Seq(fileWithInt, fileWithDouble): _*).select("myField")
Il échoue avec ce qui suit
Java.lang.UnsupportedOperationException: org.Apache.parquet.column.values.dictionary.PlainValuesDictionary$PlainDoubleDictionary
at org.Apache.parquet.column.Dictionary.decodeToInt(Dictionary.Java:48)
En cas de doublé
val schema = StructType(Seq(new StructField("myField", DoubleType)))
Je reçois
Java.lang.UnsupportedOperationException: org.Apache.parquet.column.values.dictionary.PlainValuesDictionary$PlainIntegerDictionary
at org.Apache.parquet.column.Dictionary.decodeToDouble(Dictionary.Java:60)
Est-ce que quelqu'un connaît ce problème autrement que par le retraitement des données source?.
En fonction du nombre de fichiers que vous allez lire, vous pouvez utiliser l'une de ces deux approches:
Ce serait mieux pour un plus petit nombre de limes de parquet
def merge(spark: SparkSession, paths: Seq[String]): DataFrame = {
import spark.implicits._
paths.par.map {
path =>
spark.read.parquet(path).withColumn("myField", $"myField".cast(DoubleType))
}.reduce(_.union(_))
}
Cette approche sera préférable pour traiter un grand nombre de fichiers car elle gardera la lignée courte
def merge2(spark: SparkSession, paths: Seq[String]): DataFrame = {
import spark.implicits._
spark.sparkContext.union(paths.par.map {
path =>
spark.read.parquet(path).withColumn("myField", $"myField".cast(DoubleType)).as[Double].rdd
}.toList).toDF
}