代码之家  ›  专栏  ›  技术社区  ›  Hemanth Gowda

编码器的使用速度如何比java序列化快得多?

  •  1
  • Hemanth Gowda  · 技术社区  · 7 年前

    如何使用编码器比java和kryo序列化快得多?

    2 回复  |  直到 7 年前
        1
  •  4
  •   Alper t. Turker    7 年前
    • 因为 Encoders 为了表现牺牲共性。这个想法并不新鲜。为什么Kryo比Java序列化更快?出于同样的原因。考虑一下这份成绩单:

      scala> val spark = SparkSession.builder.config("spark.serializer", "org.apache.spark.serializer.JavaSerializer").getOrCreate()
      spark: org.apache.spark.sql.SparkSession = org.apache.spark.sql.SparkSession@1ed28f57
      
      scala> val map = Map[String, Int]("foo" -> 1).withDefaultValue(0)
      map: scala.collection.immutable.Map[String,Int] = Map(foo -> 1)
      
      scala> map("bar")
      res1: Int = 0
      
      scala> val mapSerDe = spark.sparkContext.parallelize(Seq(map)).first
      mapSerDe: scala.collection.immutable.Map[String,Int] = Map(foo -> 1)
      
      scala> mapSerDe("bar")
      res2: Int = 0
      

      与…相比

      scala> val spark = SparkSession.builder.config("spark.serializer", "org.apache.spark.serializer.KryoSerializer").getOrCreate()
      spark: org.apache.spark.sql.SparkSession = org.apache.spark.sql.SparkSession@5cef3456
      
      scala>  val map = Map[String, Int]("foo" -> 1).withDefaultValue(0)
      map: scala.collection.immutable.Map[String,Int] = Map(foo -> 1)
      
      scala> map("bar")
      res7: Int = 0
      
      scala>  val mapSerDe = spark.sparkContext.parallelize(Seq(map)).first
      mapSerDe: scala.collection.immutable.Map[String,Int] = Map(foo -> 1)
      
      scala> mapSerDe("bar")
      java.util.NoSuchElementException: key not found: bar
        at scala.collection.MapLike$class.default(MapLike.scala:228)
        at scala.collection.AbstractMap.default(Map.scala:59)
        at scala.collection.MapLike$class.apply(MapLike.scala:141)
        at scala.collection.AbstractMap.apply(Map.scala:59)
        ... 48 elided
      

      (我找不到确切的帖子,但这个例子的想法来自开发者列表)。

      正如您所见,Kryo虽然速度更快,但并不能处理所有可能的情况。它关注最常见的问题,而且做得很好。

      火花 编码器 做同样的事,但更不一般。如果您只支持16种左右的类型,并且不关心互操作性(必须与真正的序列化库一起),那么您有很多机会进行优化。

    • 不需要互操作性,您就可以更进一步。原子类型的编码器就是标识。根本不需要任何转换。

    • 了解模式,如 himanshuIIITian 是另一个因素。

      为什么这很重要?因为具有定义良好的形状,所以可以优化序列化和存储。如果您知道您的数据是结构化的,那么您可以切换维度,而不是使用存储和访问成本高昂的异构行,您可以使用列式存储。

      一旦数据存储在列中,您将打开一组全新的优化机会:

      • 固定大小字段上的数据访问速度非常快,因为您可以直接访问特定地址(还记得堆外/本机内存/钨丝带来的所有兴奋吗?)。
      • 您可以使用多种压缩和编码技术来最小化数据的大小。

      这种想法也不是什么新鲜事。柱状数据库、存储格式(如Parquet)或为分析设计的现代序列化格式(如Arrow)使用了相同的想法,并且往往将这些想法推得更远(零拷贝数据共享)。

    • 不幸的是,编码器并不是万能的。存储非标准对象 is a mess ,集合编码器可以 very inefficient

        2
  •  0
  •   himanshuIIITian    7 年前

    简单-编码器知道记录的模式。这就是它们如何提供更快的序列化和反序列化(与默认的Java或Kryo序列化程序相比)。

    供参考- https://jaceklaskowski.gitbooks.io/mastering-spark-sql/spark-sql-Encoder.html