spark-RDD、DF、DS

RDD,DataFrame,DataSet的区别?

1. RDD

分布式的容器,与传统的单机容器相比,提供计算的分配和调度、计算API(算子)、计算优化、容错、缓存、广播变量+累加器。其中容错和缓存称之为弹性,分区称之为分布式。
RDD是分布式java对象的集合,所以RDD是有泛型的。但这个泛型有局限。

{1} 优点:

{2} 缺点:

序列化和反序列化的性能开销

无论是集群间的通信, 还是 IO 操作都需要对对象的结构和数据进行序列化和反序列化。

GC 的性能开销,频繁的创建和销毁对象, 势必会增加 GC

2. DataFrame

DataFrame 引入了 schema 和 off-heap

有schema 就意味着 RDD 每一行的数据的结构都是一样的,这个结构就存储在 schema 中。 Spark 通过 schema 就能够读懂数据, 因此在通信和 IO 时就只需要序列化和反序列化数据,而结构的部分就可以省略了,可以提高IO效率。
在这里插入图片描述
有了schema,我们就可以做一些结构化数据才支持的操作了。比如groupby、where、sum等等。这些结构化数据操作的灵活度要比RDD的map、filter等操作大得多。
而且优化也方便了很多。

{1} DF对比RDD

  • RDD本质还是为了操作数据,如果数据是结构化的,用sql的方式会大大简化操作,提高效率,并且spark对sparksql进行了自动优化。
    • 所谓结构化数据,就是以二维行列的方式进行组织的数据,这种数据的列只有名称没有类型,此时会有疑问,数据库中的列明明是有类型的啊?但这种类型其实是为了在硬盘保存时进行优化,并不像OOP中的类型一样是为了抽象数据。所以df的数据说白了就是在原来多行数据的基础上又添加了列的信息。使得可以以列为单位使用sql来操作数据。
    • 有些数据本身就是结构化的,也就是带有列名的,比如csv、parquet文件、json文件、hive表、jdbc连接关系型数据库,这些可以直接创建df。有些数据只有一维,也就是只有行没有列,比如RDD中的数据。可以通过设置struct也就是列的名称和类型来创建df。
      /**
      schema:StructType = StructType(Seq(StructField(DataTypes)))
      */
      val schema:StructType = StructType(Array(StructField("id", DataTypes.IntegerType), StructField("age", DataTypes.IntegerType)))
      

dataFrame比RDD多了数据的结构信息,就是schema,通过Row对象或者Struct对象来表示。
DataFrame 提供了详细的结构信息,可以让sparkSQL清楚的知道数据集中包含哪些列,列的名称和类型各是什么

  • RDD是分布式的 Java对象的集合。DataFrame是分布式的Row对象的集合。DataFrame除了提供了比RDD更丰富的算子以外,更重要的特点是提升执行效率、减少数据读取以及执行计划的优化,比如filter下推、裁剪等。
  1. 提升执行效率

    RDD API是函数式的,强调不变性,在大部分场景下倾向于创建新对象而不是修改老对象。这一特点虽然带来了干净整洁的API,却也使得Spark应用程序在运行期倾向于创建大量临时对象,对GC造成压力。在现有RDD API的基础之上,我们固然可以利用mapPartitions方法来重载RDD单个分片内的数据创建方式用复用可变对象的方式来减小对象分配和GC的开销,但这牺牲了代码的可读性,而且要求开发者对Spark运行时机制有一定的了解,门槛较高。另一方面,Spark SQL在框架内部已经在各种可能的情况下尽量重用对象,这样做虽然在内部会打破了不变性,但在将数据返回给用户时,还会重新转为不可变数据。利用 DataFrame API进行开发,可以免费地享受到这些优化效果。

  2. 减少数据读取

    分析大数据,最快的方法就是 —— 忽略它。这里的“忽略”并不是熟视无睹,而是根据查询条件进行恰当的剪枝。

    当查询的过滤条件中涉及到分区列时,我们可以根据查询条件剪掉肯定不包含目标数据的分区目录,从而减少IO。

    对于一些“智能”数据格式,比如RCFile、ORC、Parquet等列式存储格式,Spark SQL还可以根据数据文件中附带的统计信息来进行剪枝。简单来说,在这类数据格式中,数据是分段保存的,每段数据都带有最大值、最小值、null值数量等 一些基本的统计信息。当统计信息表名某一数据段肯定不包括符合查询条件的目标数据时,该数据段就可以直接跳过(例如某整数列a某段的最大值为100,而查询条件要求a > 200)。仅扫描查询真正涉及的列,忽略其余列的数据。

3. DataSet

DataSet 结合了 RDD 和 DataFrame 的优点,并带来的一个新的概念 Encoder。

当序列化数据时,Encoder 产生字节码与 off-heap 进行交互,能够达到按需访问数据的效果,而不用反序列化整个对象,比如访问某个属性时,DF需要将整个ROW反序列化构建到内存中。
目前Spark 还没有提供自定义 Encoder 的 API,但是未来会加入。

三者之间的转换:
在这里插入图片描述

{1} 优点

编译时类型安全,编译时就能检查出类型错误
面向对象的编程风格,直接通过类名点的方式来操作数据

{2} 同df的关系

DataFrame是Dataset的一个特例,DataFrame就是Dataset[Row],每一行的类型是Row,用Row这个类来表示schema,df是按命名列方式组织的一个 Dataset。在 Scala API 中, DataFrame 仅仅只是 Dataset[Row] 的一个类型别名,而在 Java API 中, 开发人员需要使用 Dataset<Row> 来 表示一个 DataFrame,Spark中没有DataFrame类。

df对应的数据存的根本就不是对象,每行有哪些字段,这些字段的类型都不可获取。自然不能用对象的方式去操作,只能用上面提到的getAS方法或者共性中的拿出特定字段。Dataset每一个record存储的是一个强类型值而不是一个Row。
正常来说是不能通过列名来取的,当然spark做了优化,可以通过getAs[T](fieleName)来通过列名直接取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值