(1).三者区别和联系
DataFrame:
DataFrame是以rdd为基础的分布式数据集,类似于传统数据库的二维表格,带有schema的元数据,即相当于二维表格的每一列都有列名和类型,基于次对于dataFrame的操作更有正对性,
优点:引入了Schema,用于管理数据类型 Datafram中的每一行数据类型都是row,所以在序列化和反序列化的时候就不需要对数据类型操作;Dataframe不受jvm的限制,引入了off-head的概念,就是堆以外的内存,直接受操作系统来管理。
缺点:不是面向对象的操作,不是编译时类型安全。
Rdd:
弹性分布式数据集,是一个抽象概念,由partition组成,partition和数据块一一对应,比如spark加载hdfs中的数据,rdd的分区数由hdfs中的数据块决定的。一般情况下,这个分区数我们无法去左右,比如giz压缩的文件,再加载的时候实现不了分区,但是可以通过reparations进行分区处理。
优点:编译时类型安全,就是在编译期间可以检查类型;面向对象的操作方式
缺点:序列化和反序列化有较大的性能开销,就是在集群或者io都需要对数据和类型序列化和反序列化
Dataset:
继rdd和DataFrame推出来的分布式数据集,引入了encode概念,虽然DataFrame相对于Rdd引入了Schema,在序列化和反序列的只需要针对数据操作,但是还是需要对整个数据操作,而dataset引入的encode,可以实现按需访问数据,不需要序列化整个对象。
(2).三者相互转换
1.DataFrame/Dataset转RDD:
val rdd1=testDF.rdd
val rdd2=testDS.rdd
2.RDD转DataFrame:
①在toDF中指定字段名
②引入 spark.implicits._ 是为了RDD和DataFrame之间的隐式转换
import spark.implicits._
val rdd=sc.parallelize(List(("apple",1),("strawberry",2)))
val testDF = rdd.toDF("name","age")
3.RDD转Dataset:
①引入隐式转换
②自定义的Case Class设置为全局变量
import spark.implicits._
val rdd=sc.parallelize(List(("apple",1),("strawberry",2)))
case class Person(name:String,age:Int) //定义字段名和类型
val testDS = rdd.map {x=>Person(x._1,x._2)}.toDS
4.Dataset转DataFrame:
①引入隐式转换
import spark.implicits._
val testDF = testDS.toDF
5.DataFrame转Dataset:
①引入隐式转换
②自定义的Case Class设置为全局变量
③case class 的ElementType 要和DF中的一致
import spark.implicits._
val rdd=sc.parallelize(List(("apple",1),("strawberry",2)))
val testDF = rdd.toDF("name","age")
case class Person(name:String,age:Int) //定义字段名和类型
val testDS = testDF.as[Person]