30天搞定spark源码系列-rdd dataset dataframe的区别

阅读本篇文章,你预期可以得到下面几个问题的答案:

  1. Rdd DataSet DataFrame的区别
  2. Row类型是什么
  3. Row格式是怎么存储的

1、Rdd

RDD(Resilient Distributed Dataset)弹性分布式数据集,是spark框架中最基本的抽象元素。具有不可变,可伸缩、易并行的特点;

它具有几个比较重要的属性:

  • 一系列分片;就是partition的概念,主要是为了实现并行
  • 对于每个分片都会参与到一次计算中
  • RDD存在相互依赖的关系,这也是spark的DAG以及算子依赖的思想
  • 自定义的分区函数;目前spark已经实现的,常用的hash和range;
  • 自定义的分区函数;目前spark已经实现的,常用的hash和range

优点:

  1. 存储的是java对象,类型转换安全
  2. 通用的,对于结构化和非结构化的数据都可以处理;

缺点:

  1. 存储的java对象,在传输过程中需要进行序列化,默认的序列化速度慢;
  2. java对象,意味着会有频繁的GC;
  3. 比较原始,不存在谓词下推等优化手段;

2、DataFrame

dataframe可以简单理解为一张二维表,拥有表头(schema)的概念,可以很方便的让spark运行过程中知道数据的组织形式;同时开发人员也可以基于schema进行数据的转换和操作;

相比Rdd:

2.1、相同点

  1. 都是分布式数据集;
  2. 都是不可变的数据集;
  3. 都拥有很丰富的算子操作;

2.2、不同点

  1. rdd存储类型为java对象,dataframe存储类型为dataset[Row],有schema的定义,开发者可以通过列名获取对应列的数据;
  2. rdd执行是按照定义的算子进行计算,而dataframe是拥有比rdd更多的操作算子,同时有一些更深层次的优化:例如谓词下推;

3、Dataset

Dataset是强类型、特定域的、能并行执行的的数据集合;
而每一个Dataset都有一个特定的实例:DataFrame,它是Dataset[Row]类型
相比DataFrame:

3.1、DataFrame vs Dataset

和前面说的一致:每一个Dataset都有一个特定的实例:DataFrame,它是Dataset[Row]类型

可以理解为:DataFrame是Dataset的一种类型下的表现形式。如果你是用scala开发spark的程序,那对于类型这块的感知不是那么的明显,如果你是使用java开发spark的程序的话你会注意到一个现象:使用spark.sql()返回的明明是一个DataFrame,但是对象的类型却只能定义为Dataset[Row],是不是还有过怀疑呢??从定义来看,人家DataFrame只是Dataset在18岁的容颜而已。

3.2、Dataset结构

Dataset和rdd一样,也有几个相同的属性:

  1. 惰性执行
  2. 有两类算子:transform和action

那么为了spark为了支持Dataset定义的这种特定域的情况下,spark到底是怎么实现的呢?
在这里插入图片描述
每一个Dataset都有一个encoder编码器,它是把泛型T转换成spark内部系统可以识别的基本类型,比如int,string等;比如一个Dataset[Person]类型,在spark生成代码并序列化的时候,encoder的作用就是告诉spark,将Person里面的属性:sex,age作为基本类型序列化成二进制结构,当然带来的好处就是较少的内存占用和更高效的数据处理速度;

4、rdd DataFrame转换

对于一个rdd转化为DataFrame的操作非常简单:

val df = rdd.toDF()
val df = rdd.toDF("id","name")

那么他具体的实现是什么呢?需要研究一下toDF函数
在这里插入图片描述

  1. 判断rdd的tuple的元素的个数和输入的colNames是不是一一对应的;
  2. 进行列和列名的匹配;logicalPlan.output.zip(colNames)匹配是通过scala集合直接的zip拉链操作实现,所以在toDF函数输入的列名顺序要和rdd元素的顺序完全一致,这里需要特别小心。

5、Row

前面知道DataFrame是Dataset[Row]的格式,那么就需要了解一下spark的Row到底是什么,以什么格式存储数据的;

我们先直观想一下,Row,中文含义:行;
哦,那他肯定就是行存储的,意思是将同一行的数据汇聚到一起作为一个Row;恭喜你,确实如此,Row就是一行数据,Row有两个基本的操作:

  1. 构建:Row()和Row.fromSeq两种方式
  2. 获取数据:获取数据是通过索引号来获取,实现的方法有很多个:getString(i)等

下面是spark支持的类型和java基本类型的对应关系:
在这里插入图片描述

既然是行,那存储方式就是数组了呀;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值