为什么在Spark中创建数据集需要编码器

hat*_*lla 3 scala apache-spark

我想以拼花形式编写输出文件。为此,我将RDD转换为数据集,因为从RDD无法直接获得实木复合地板形式。对于创建数据集,我们需要使用隐式编码器,否则,它将开始产生编译时错误。我仅在这方面有几个问题。以下是我的代码:

implicit val myObjEncoder = org.apache.spark.sql.Encoders.kryo[ItemData]
    val ds: Dataset[ItemData] = sparkSession.createDataset(filteredRDD)

    ds.write
      .mode(SaveMode.Overwrite)
      .parquet(configuration.outputPath)
  }
Run Code Online (Sandbox Code Playgroud)

以下是我的问题:

  1. 为什么在创建数据集时使用编码器很重要?这个编码器做什么?
  2. 从上面的代码中,当我得到实木复合地板形式的输出文件时,我看到了编码形式的文件。如何解码?当我使用base64格式对其进行解码时,得到以下信息:com ......... processor.spark.ItemDat“ 0156028263

因此,基本上它向我展示了object.toString()的一种值。

ulu*_*eyn 5

文档

createDataset需要编码器将类型的JVM对象T与内部Spark SQL表示形式相互转换。

希瑟·米勒的课程中

基本上,编码器是在JVM对象和Spark SQL的专用内部(表格)表示形式之间转换数据的功能。所有数据集都需要它们!

编码器是高度专业化和经过优化的代码生成器,可生成用于数据序列化和反序列化的自定义字节码。

我相信现在很清楚什么是编码器以及它们做什么。关于第二个问题,Kryo序列化程序导致Spark 将数据集中的每一行存储为平面二进制对象。而不是使用JavaKryo串行器,你可以用星火内部的编码器。您可以通过自动使用它spark.implicits._。它使用的内存也少于Kryo/ Java序列化。

更新我

根据您的评论,以下是使Spark编码器不同于常规JavaKryo序列化的东西(来自Heather Miller的课程):

  • 仅限于图元和案例类(Spark SQL数据类型),并且最适合用于此类。
  • 它们包含架构信息,这些信息使这些高度优化的代码生成器成为可能,并能够基于数据的形状进行优化。由于Spark理解数据集中的数据结构,因此可以在缓存数据集时在内存中创建更优化的布局。
  • Kryo序列Java快10倍以上(序列化速度慢几个数量级)

希望对您有所帮助!