Spark RDD、DataFrame、Dataset的区别

Resilient Distributed Dataset (RDD)

RDD是一个不可变的分布式的数据元素集合,RDD中的元素在集群上是分区的,提供了Transformation和Action两种并行操作。

优点:强类型,编译时类型安全,符合面向对象的编程思想,可以处理结构化数据和非结构化数据

缺点:默认采用的是Java序列化方式,无论是集群间的通信,还是IO操作都需要对对象的结构和数据进行序列化和反序列化,序列化的开销很大,而且数据存储在java堆内存中,导致gc比较频繁。因为RDD可以处理任何类型的数据,所以它对任何类型数据都没做优化,所以在处理结构化数据时没有SQL方便。

什么时候使用RDD?

  • 只需要对数据集进行低层次的转换和操作
  • 待处理的数据是非结构化数据
  • 希望自己实现一些功能编程来操作数据,而不是用特定域的表达式来操作数据(如:SQL)
  • 不关注数据的schema信息
  • 对于结构化和半结构化数据,可以放弃DataFrame和Dataset对它们的优化

在Spark 2.X中还需要学习RDD吗?RDD重要吗?

答案是肯定的,RDD和DataFrame、Dataset之间通过一些简单的API就能进行转化,而且DataFrame和Dataset是构建在RDD之上。

DataFrame和Dataset

和RDD类似,DataFrame也是一个分布式数据集。DataFrame引入了schema和off-heap的概念。RDD每一行的数据, 结构都是一样的,这个结构就存储在schema中。 Spark通过schema就能够读懂数据, 因此在通信和IO时就只需要序列化和反序列化数据, 而结构的部分就可以省略了(就像数据库中的一张表一样)。

优点:处理结构化数据非常方便,支持Avro、CSV、ElasticSearch和Cassandra等KV数据,也支持Hive tables、MySQL等传统数据表。有针对性的优化,如采用Kryo序列化,由于数据结构元信息spark已经保存,序列化时不需要带上元信息,大大的减少了序列化大小,而且数据保存在堆外内存中,减少了gc次数,所以运行更快。

缺点:编译时不能类型转化安全检查,运行时才能确定是否有问题。对于对象支持不友好,RDD内部数据直接以Java对象存储,DataFrame内部存储的是Row对象而不能是自定义对象。

DataSet结合了RDD和DataFrame的优点,并带来的一个新的概念Encoder。当序列化数据时,Encoder产生字节码与off-heap进行交互,能够达到按需访问数据的效果,而不用反序列化整个对象。

优点:支持结构化和非结构化数据。和RDD一样,支持自定义对象存储。和DataFrame一样,支持结构化数据的SQL查询。采用堆外内存存储,gc友好。类型转化安全,代码友好。

Spark RDD、DataFrame、Dataset的区别

自Spark2.0之后,DataFrame和Dataset合并为更高级的Dataset,新的Dataset具有两个不同的API特性:

  • 非强类型(untyped),DataSet[Row]是泛型对象的集合,它的别名是DataFrame
  • 强类型(strongly-typed),DataSet[T]是具体对象的集合,如Scala和Java中定义的类

什么时候使用DataFrame或Dataset?

  • 如果你想要丰富的语义、高层次的抽象和特定情景的API,使用DataFrame或Dataset。
  • 如果你的处理要求涉及到filters、maps、aggregation、averages、sum、SQL queries、columnar access或其他lambda匿名函数,使用DataFrame或Dataset。
  • 如果希望在编译时获得更高的类型安全性,需要类型化的JVM对象,利用Tungsten编码进行高效的序列化、反序列化,使用DataSet。
  • 如果你想统一和简化Spark的API,使用DataFrame或Dataset。
  • 如果你是一个R用户,使用DataFrame。
  • 如果你是一个Python用户,使用DataFrame,如果你需要更多的控制功能,尽量回到RDD。

如何选择RDD还是DataFrame or Dataset

前者提供低级别的功能和更多的控制,后者允许自定义视图和结构,提供高级和特定领域的操作,节省空间,并能够以极高的速度执行。