繁体   English   中英

在 Java Spark Job 中使用 avro 模式 (avsc) 将 avro 数据写入 s3

[英]Using avro schema (avsc) for writing avro data to s3 in Java Spark Job

我想使用提供的 Avro 模式而不是 Spark 的自动生成模式以 Avro 格式编写 DataFrame。 如何告诉 Spark 在写入时使用我的自定义架构?

{
  "type" : "record",
  "name" : "name1",
  "namespace" : "com.data"
  "fields" : [
  {
    "name" : "id",
    "type" : "string"
  },
  {
    "name" : "count",
    "type" : "int"
  },
  {
    "name" : "val_type",
    "type" : {
      "type" : "enum",
      "name" : "ValType"
      "symbols" : [ "s1", "s2" ]
    }
  }
  ]
}
  1. 使用 avroSchema 进行 avro 阅读。 在这一步一切正常。

    数据集 d1 = spark.read().option("avroSchema",String.valueOf(inAvroSchema)).format("com.databricks.spark.avro").load("s3_path");

  2. 在这里,我对上述数据执行了一些 spark.sql 并存储到 DataFrame。

  3. 当我尝试基于 avro 模式将 avro 数据写入 s3 时

DF 数据类型:

root
 |-- id: string (nullable = true)
 |-- count: integer (nullable = true)
 |-- val_type: string (nullable = true)

FinalDF.write().option("avroSchema",String.valueOf(inAvroSchema)).format("com.databricks.spark.avro").mode("overwrite").save("target_s3_path");

我得到了错误:

User class threw exception: org.apache.spark.SparkException: Job aborted.
    ......
    Caused by: org.apache.avro.AvroRuntimeException: **Not a union: "string"**
        at org.apache.avro.Schema.getTypes(Schema.java:299)
        at 
org.apache.spark.sql.avro.AvroSerializer.org$apache$spark$sql$avro$AvroSerializer$$resolveNullableType(AvroSerializer.scala:229)

有什么方法可以使用 avro 模式来编写 avro 数据,或者如果它是正确的方法(使用"option("avroSchema",String.valueOf(inAvroSchema))" ) - 可能是我做错了什么? "forceSchema" option在我的情况下不起作用。

提前致谢。

我做了一些挖掘,发现了一些有趣的东西,

case class Name1(id: String, count: Int, val_type: String)

val schema = """{
                   |  "type" : "record",
                   |  "name" : "name1",
                   |  "namespace" : "com.data",
                   |  "fields" : [
                   |  {
                   |    "name" : "id",
                   |    "type" : "string"
                   |  },
                   |  {
                   |    "name" : "count",
                   |    "type" : "int"
                   |  },
                   |  {
                   |    "name" : "val_type",
                   |    "type" : {
                   |      "type" : "enum",
                   |      "name" : "ValType",
                   |      "symbols" : [ "s1", "s2" ]
                   |    }
                   |  }
                   |  ]
                   |}""".stripMargin


val d = Seq(Name1("1",2,"s1"),Name1("1",3,"s2"),Name1("1",4,"s2"),Name1("11",2,"s1")).toDF()

d.write.mode(SaveMode.Overwrite).format("avro").option("avroSchema",schema).save("data/tes2/")

当我使用 spark 2.4.x 执行代码时,上面的代码失败,但是当我使用新的 Spark 3.0.0 运行相同的代码时,代码成功并且数据被成功写入。

val df = spark.read.format("avro").load("data/tes2/")
df.printSchema()
df.show(10)

root
 |-- id: string (nullable = true)
 |-- count: integer (nullable = true)
 |-- val_type: string (nullable = true)

+---+-----+--------+
| id|count|val_type|
+---+-----+--------+
| 11|    2|      s1|
|  1|    4|      s2|
|  1|    3|      s2|
|  1|    2|      s1|
+---+-----+--------+

我想最好的办法是升级 spark 版本或更改 avro 模式定义。

您可以使用org.apache.spark:spark-avro package 并尝试在to_avro function 上设置avroSchema选项。 这是文档: https://spark.apache.org/docs/latest/sql-data-sources-avro.html#to_avro-and-from_avro

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM