如何使用spark读取以avro逻辑格式存储的hive双值

p3rjfoxz  于 2021-06-28  发布在  Hive
关注(0)|答案(1)|浏览(553)

我有以avro格式存储的现有配置单元数据。无论出于什么原因,通过执行select读取这些数据都非常慢。我还不知道为什么。数据是分区的,我的where子句总是跟在分区列后面。所以我决定通过导航到分区路径并使用sparksqlcontext直接读取数据。这工作得快多了。但是,我的问题是读取双值。avro以二进制格式存储它们。在配置单元中执行以下查询时:

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

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

fdx2calv

fdx2calv1#

我找到了将avro模式转换为sparksql结构类型的部分解决方案。databricks开发的com.databricks.spark.avro.schemaConverter在转换tosqltype(avroschema:schema)方法中的avro逻辑数据类型时存在错误,该方法错误地转换了logicaltype

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

进入之内

StructField("MyDecimalField",BinaryType,true)

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

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)

这是我坚持在这个时候,如果有人能建议下一步做什么或任何其他工作。

相关问题