【发布时间】:2017-04-17 01:43:03
【问题描述】:
我遇到了一个问题,我在 S3 中将 Parquet 数据作为每日块(以 s3://bucketName/prefix/YYYY/MM/DD/ 的形式),但我无法从不同日期读取 AWS EMR Spark 中的数据,因为某些列类型不匹配,我获取许多异常之一,例如:
java.lang.ClassCastException: optional binary element (UTF8) is not a group
出现在某些文件中有一个数组类型具有值但同一列在其他文件中可能具有null 值,然后被推断为字符串类型。
或
org.apache.spark.SparkException: Job aborted due to stage failure: Task 23 in stage 42.0 failed 4 times, most recent failure: Lost task 23.3 in stage 42.0 (TID 2189, ip-172-31-9-27.eu-west-1.compute.internal):
org.apache.spark.SparkException: Failed to merge incompatible data types ArrayType(StructType(StructField(Id,LongType,true), StructField(Name,StringType,true), StructField(Type,StringType,true)),true)
我有 JSON 格式的 S3 原始数据,我最初的计划是创建一个自动作业,它启动一个 EMR 集群,读取上一个日期的 JSON 数据,然后简单地将其作为 parquet 写回 S3。
JSON 数据也分为日期,即键具有日期前缀。读取 JSON 工作正常。无论当前正在读取多少数据,都会从数据中推断出架构。
但是在写入 parquet 文件时问题就出现了。据我了解,当我使用元数据文件编写镶木地板时,这些文件包含镶木地板文件的所有部分/分区的架构。在我看来,这似乎也可以使用不同的模式。当我禁用写入元数据时,据说 Spark 会从给定 Parquet 路径中的第一个文件推断整个架构,并假定它在其他文件中保持不变。
当某些应该是double 类型的列在给定日期只有整数值时,从 JSON 中读取它们(这些数字是整数,没有浮点数)使 Spark 认为它是一个具有类型的列long。即使我可以在编写 Parquet 文件之前将这些列加倍,这仍然不好,因为架构可能会更改,可以添加新列,并且无法跟踪。
我看到有些人有同样的问题,但我还没有找到足够好的解决方案。
对此有哪些最佳做法或解决方案?
【问题讨论】:
标签: apache-spark apache-spark-sql spark-dataframe emr parquet