如果我有一个数据集,其中每个记录都是一个案例类,我将如下所示保留该数据集,以便使用序列化:
myDS.persist(StorageLevel.MERORY_ONLY_SER)
Spark是否使用java / kyro序列化来序列化数据集?或者就像数据帧一样,Spark有自己的方式将数据存储在数据集中?
Spark Dataset
不使用标准序列化器。相反,它使用Encoders
,它“理解”数据的内部结构,并且可以有效地将对象(具有Encoder
的任何东西,包括Row
)转换为内部二进制存储。
使用Kryo或Java序列化的唯一情况是,当你explicitly apply Encoders.kryo[_]
或Encoders.java[_]
。在任何其他情况下,Spark将对对象表示进行解构并尝试应用标准编码器(原子编码器,Prodcuct
编码器等)。与Row
相比唯一的区别是它的Encoder
- RowEncoder
(在某种意义上,Encoders
与镜头类似)。
Databricks在Encoder
中明确地将Dataset
/ Introducing Apache Spark Datasets序列化与Java和Kryo序列化器进行对比(特别是对于带编码器的Lightning-fast序列化部分)
图像来源
Dataset[SomeCaseClass]
与Dataset[Row]
或任何其他Dataset
没有什么不同。它使用相同的内部表示(在需要时映射到外部类的实例)和相同的序列化方法。
因此,不需要直接对象序列化(Java,Kryo)。
在引擎盖下,数据集是RDD。来自documentation for RDD persistence:
将RDD存储为序列化Java对象(每个分区一个字节数组)。这通常比反序列化对象更节省空间,特别是在使用快速序列化器时,但读取CPU密集程度更高。
默认情况下,使用Java序列化source:
默认情况下,Spark使用Java的ObjectOutputStream框架序列化对象... Spark还可以使用Kryo库(版本2)更快地序列化对象。
要启用Kryo,请使用SparkConf初始化作业并将spark.serializer
设置为org.apache.spark.serializer.KryoSerializer
:
val conf = new SparkConf()
.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
val sc = new SparkContext(conf)
在创建SparkContext之前,您可能需要使用Kryo注册类:
conf.registerKryoClasses(Array(classOf[Class1], classOf[Class2]))