一、概述
Spark在RDD基础上,提供了DataFrame与DataSet用户编程接口,在跨语言方面具有很好的支持。
二、DataFrame
DataFrame与RDD一样,都是不可变分布式弹性数据集。不同之处在于RDD中的数据不包含任何架构信息,数据的内部结构可以看作黑盒,因此直接使用RDD时需要开发人员实现特定的函数来完成数据结构的解析;而dataFrame中的数据集类似于关系数据库中的表,按列名存储,具有Schema信息,开发人员可以直接将结构化数据集导入DataFrame。DataFrame的数据抽象是命名元组(对应Row类型),相比RDD多了数据特性,因此可以进行更多的优化。
例如,使用 DataFrame 实现 Word Count ,构造 RDD 之后,直接用 toDF 得到只有一列(列名
为“line 勺的 DataFrame ,然后调用 explode 方法将一行数据展开,最后使用 groupBy 方法完成
聚合逻辑
val linesDF = sc. textFile (”hdfs: // ...”) .toDF (”line”)
val rdsDF = linesDF.explode ("line ","world") ((line: String) => line. split (",")
val wordCountDF = wordsDF.groupBy("word").count()
wordCountDF. collect()
三、DataSet
Dataset 是比 DataFrame 更为强大的 API ,如图 3.1 所示,两者整合之后 DataFrame 本质上是一种特殊的 Dataset (Dataset[Row]类型) Dataset 具有两个完全不同的 API 特征强类型
(Strongly-Typed) API 和弱类型(Untyped) API。 强类型一般通过 Scala 中定义的 Case Class 或 Java中的中的Class来指定。
作为 DataFrame 的扩展, Dataset 结合了 RDD DataFrame 的优点,提供类型安全和面向对
象的编程接口,并引入了编码器(Encoder )的概念 典型的 Dataset 创建与使用案例如下,其
中定义的 Person 类就起到了 Encoder 的作用 在映射的过程中, Encoder 首先检查定义的 Person
类的类型是否与数据相符,如果不相符(例如 age 宇段大于 Long 的最大值等),则能够及时提
供有用的错误信息,防止以不正确的方式处理数据 类似于 DataFrame, Dataset 创建之后也能
够很容易地使用 lambda 表达式进行各种转换操作
case class Person(name: String, age:Int)
val caseClassDS = Seq(Persso(”Andy 32)) .toDS()
caseClassDS.show()
Encoder 不仅能够在编译阶段完成类型安全检查,还能够生成字节码与堆外数据进行交互,
提供对各个属性的按需访问,而不必对整个对象进行反序列化操作,极大地减少了网络数据传
输的代价 此外, DataFrame Dataset 这些高级的 API ,能够利用 park SQL 中的 Optimizer
Tungsten 技术自动完成存储和计算的优化,降低内存使用,并极大地提升性能