我正在使用Spark 2.4并指 https://spark.apache.org/docs/latest/rdd-programming-guide.html#rdd-persistence
Bean类:
public class EmployeeBean implements Serializable {
private Long id;
private String name;
private Long salary;
private Integer age;
// getters and setters
}
火花示例:
SparkSession spark = SparkSession.builder().master("local[4]").appName("play-with-spark").getOrCreate();
List<EmployeeBean> employees1 = populateEmployees(1, 1_000_000);
Dataset<EmployeeBean> ds1 = spark.createDataset(employees1, Encoders.kryo(EmployeeBean.class));
Dataset<EmployeeBean> ds2 = spark.createDataset(employees1, Encoders.bean(EmployeeBean.class));
ds1.persist(StorageLevel.MEMORY_ONLY());
long ds1Count = ds1.count();
ds2.persist(StorageLevel.MEMORY_ONLY());
long ds2Count = ds2.count();
我在Spark Web UI中寻找存储空间。有用的部分-
ID RDD Name Size in Memory
2 LocalTableScan [value#0] 56.5 MB
13 LocalTableScan [age#6, id#7L, name#8, salary#9L] 23.3 MB
几个问题:
Kryo序列化RDD的大小应该小于Java序列化RDD的大小,而不是大于两倍吗?
我还尝试了MEMORY_ONLY_SER()
模式,并且RDD大小相同。作为序列化Java对象的RDD应该存储为每个分区一个字节数组。持久的RDD的大小不应该小于反序列化的RDD的大小吗?
在创建数据集时添加Kryo和bean编码器到底在做什么?
我可以重命名持久的RDD以获得更好的可读性吗?
答案 0 :(得分:1)
kryo序列化RDD的大小应该小于Java序列化RDD的大小,而不是大于两倍吗?
如果您曾经使用过Java序列化(或RDD),那将是正确的。但是,事实并非如此。当您应用Encoders.javaSerialization
时,将使用Java序列化,该Encoders.product
与Encoders.kryo
一样,使用二进制序列化。
二进制序列化器获取一个完整的对象,使用通用序列化工具对其进行序列化,并将结果字节数组存储为单个DataFrame
列。对于优化器来说,结果是不透明的(没有真正的存储优化,因为blob无法很好地压缩),并且只能与功能性(“强类型” API)一起使用。
Encoders.bean
是与Spark Encoders: when to use beans()类似的完全不同的野兽。它利用了类的结构,并反映在架构中。因为它对单个字段进行编码,所以可以使用标准的Spark方法有效地压缩列。因此,较低的存储内存需求。