【问题标题】:How using Spark read Hive DOUBLE value stored in Avro logical format如何使用 Spark 读取以 Avro 逻辑格式存储的 Hive DOUBLE 值
【发布时间】:2016-07-18 18:28:31
【问题描述】:

我有以 Avro 格式存储的现有 Hive 数据。无论出于何种原因,通过执行 SELECT 来读取这些数据都非常慢。我还没弄清楚为什么。数据是分区的,我的 WHERE 子句总是跟在分区列之后。所以我决定通过导航到分区路径并使用 Spark SQLContext 直接读取数据。这工作得更快。但是,我遇到的问题是读取 DOUBLE 值。 Avro 以二进制格式存储它们。 当我在 Hive 中执行以下查询时:

select myDoubleValue from myTable;

我得到了正确的预期值

841.79
4435.13
.....

但以下 Spark 代码:

    val path="PathToMyPartition"
    val sqlContext = new SQLContext(sc)
    val df = sqlContext.read.avro(path)
    df.select("myDoubleValue").rdd.map(x => x.getAs[Double](0))

给了我这个例外

java.lang.ClassCastException : [B cannot be cast to java.lang.Double

提供架构或将以二进制格式存储的值转换为双精度格式的正确方法是什么?

【问题讨论】:

  • 您的值是字符串格式的吗?数据框中的数据是什么格式的?
  • 当我运行 df.schema 时,相关字段的格式如下:binary (nullable = true) 所以我假设,同样基于我得到的错误,它是二进制的

标签: apache-spark binary hive double avro


【解决方案1】:

我找到了如何将 Avro 模式转换为 Spark SQL StructType 的部分解决方案。 Databricks 开发的 com.databricks.spark.avro.SchemaConverters 在其 toSqlType(avroSchema: Schema) 方法中转换 Avro 逻辑数据类型时存在错误,该方法错误地转换了logicalType

{"name":"MyDecimalField","type":["null",{"type":"bytes","logicalType":"decimal","precision":38,"scale":18}],"doc":"","default":null}

进入

StructField("MyDecimalField",BinaryType,true)

我在本地版本的代码中修复了这个错误,现在它正在转换为

StructField("MyDecimalField",DecimalType(38,18),true)

现在,以下代码读取 Avro 文件并创建一个 Dataframe:

val avroSchema = new Schema.Parser().parse(QueryProvider.getQueryString(pathSchema))
val sqlContext = new SQLContext(sc)
val df = sqlContext.read.schema(MyAvroSchemaConverter.toSqlType(avroSchema).dataType.asInstanceOf[StructType]).avro(path)

但是,当我选择我希望为十进制的字段时

df.select("MyDecimalField")

我收到以下异常:

scala.MatchError: [B@3e6e0d8f (of class [B)

这是我此时停留的地方,如果有人能建议下一步做什么或任何其他解决方法,我将不胜感激。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    • 2015-10-31
    • 2016-03-19
    • 2018-11-24
    相关资源
    最近更新 更多