DataFrame / DataSet / RDD的关系:

RDD是Spark的基石,因为其他的spark框架都是运行在Spark core上的.但是在我们Spark sql里面,就有点区别了.

在Spark sql中,DataSet是核心,没有之一.但是DataSet仅限于Spark sql中,不能在其他框架中使用,所以RDD依旧还是spark的基石,依旧是核心.而DataFrame已经被DataSet替换了,DataFrame能实现的功能,DataSet都能实现,相反,DataFrame却不能.

三者的关系如下:

RDD + schema(数据的结构信息) = DataFrame = DataSet[Row]

RDD 0.x版本发布, DataFrame1.3版本发布, DataSet1.6版本发布.

RDD: 提供了很多实用简单的API

DataFrame: DataFrame可以理解为一个传统数据库的二维表格,除了数据以外,还记录着数据的结构信息,即schema.DataFrame API提供的是一套高层的关系操作,比函数式的RDD API要更加友好

DataSet: DataSet[Row] = Dataframe ; 它是Dataframe API的一个扩展,是spark最新的数据抽象,也是Spark SQL中最核心的组件,它基本代替了Dataframe,也有完全代替Dataframe的趋势.

注: RDD不支持spark sql的操作

RDD / DataSet / Dataframe之间的转换
上面说到RDD不支持Spark sql的操作,但是Spark生态圈只提供了Spark core一个计算框架,且Spark生态圈都是基于Spark core进行计算的,所以Spark core对接Spark sql的方式就是:将RDD转换为DataSet / Dataframe,且三者之间支持互相转换!

转换之前先聊一下DataFrame支持两种查询方式:一种是DSL风格,另外一种是SQL风格,dataFrame支持两者查询风格

DSL: 你需要引入 import spark.implicit._ 这个隐式转换,可以将DataFrame隐式转换成RDD。

SQL: 你需要将DataFrame注册成一张表格,且需要通过sparkSession.sql 方法来运行你的SQL语句

用Spark-shell来操作Spark SQL,spark作为SparkSession的变量名,sc作为SparkContext的变量名.

将文件中的数据转换成DataSet //先case一个类

case class person(name:String,age:Int)

//将文件里面的数据转换成DataSet

val peopleDF2 =spark.sparkContext.textFile("../examples/src/main/resources/people.txt").map(_.split(",")).map(para=> Person(para(0).trim,para(1).trim.toInt)).toDS

//制成一张person的表

//制作一个临时表,之后就可以使用spark.sql("这里面是sql语句")
peopleDF2.createOrReplaceTempView("persons")
//查询
val teen =spark.sql("select * from persons where age between 13 and 30")
//因为DataFrame=DataSet[row],所以要访问row对象中的每一个元素,
//可以通过这种row[0]角标的方式来访问,上面是通过反射获取schema
teen.map(row => "name:" + row(0)).show
//将RDD转换成DataFrame
var peopleRDD = sc.textFile("../examples/src/main/resources/people.txt") 
peopleRDD.collect

//以”,”切割,得到一个Array,然后再用map对里面的每一个元素都进行转换,最后用toDF方法给这两个起名字,这里的para也可以是一个样例类,与下面变成DataSet一样,唯一的区别在于最后为toDF,这样的话toDF里面就不需要给定名称了
val peopleDF =peopleRDD.map(_.split(",")).map(para=>(para(0).trim(),para(1).trim().toInt)).toDF("name","age")

//将 DataFrame转换成RDD
val aa = peopleDF.rdd

//将RDD转换成DataSet
//先定义一个case实例,最后是直接toDS就ok了                                                                                
case class person(name:String,age:Int) 
val peopleDF= peopleRDD.map(_.split(",")).map(para=>person(para(0).trim(),para(1).trim().toInt)).toDS

//将DataSet转换成RDD
val bb = peopleDF.rdd        //和上面一样,一个方法搞定

//将DataFrame转换成DataSet
val peopleDS = peopleDF.as[person]           //as那个case的类,意思就是告诉每一列的类型是什么

//将DataSet转换成DataFrame 
PeopleDS.toDF                   //用的toDF方法,相当于直接把类型信息去掉