1.Rdd
RDD(Resilient Distributed Dataset)叫做分布式数据集,是Spark中最基本的数据抽象。代码中是一个抽象类,它代表一个不可变、可分区、里面的元素可并行计算的集合。
2.dateFrame
与RDD类似,DataFrame也是一个分布式数据容器
但是dataFrame 更像一个传统的二维表,既有数据.又有数据结构即schema信息
3.dateFrame和Rdd的区别
上图直观地体现了DataFrame和RDD的区别。左侧的RDD[Person]虽然以Person为类型参数,但Spark框架本身不了解Person类的内部结构。而右侧的DataFrame却提供了详细的结构信息,使得Spark SQL可以清楚地知道该数据集中包含哪些列,每列的名称和类型各是什么。DataFrame是为数据提供了Schema的视图。可以把它当做数据库中的一张表来对待,DataFrame也是懒执行的。性能上比RDD要高
总得来说dateFrame 就是在Rdd 基础上加了结构信息,并做了执行优化
4.dataSet
dataFrame 理解为二维表的话在rdd上加了结构,
dataSet 理解为类或者对象,里面字段理解为类属性,访问更简单粗暴
可以直接用面向对象语言访问
1)是Dataframe API的一个扩展,是Spark最新的数据抽象。
2)用户友好的API风格,既具有类型安全检查也具有Dataframe的查询优化特性。
3)Dataset支持编解码器,当需要访问非堆上的数据时可以避免反序列化整个对象,提高了效率。
4)样例类被用来在Dataset中定义数据的结构信息,样例类中每个属性的名称直接映射到DataSet中的字段名称。
5) Dataframe是Dataset的特列,DataFrame=Dataset[Row] ,所以可以通过as方法将Dataframe转换为Dataset。Row是一个类型,跟Car、Person这些的类型一样,所有的表结构信息我都用Row来表示。
6)DataSet是强类型的。比如可以有Dataset[Car],Dataset[Person].
7)DataFrame只是知道字段,但是不知道字段的类型,所以在执行这些操作的时候是没办法在编译的时候检查是否类型失败的,比如你可以对一个String进行减法操作,在执行的时候才报错,而DataSet不仅仅知道字段,而且知道字段类型,所以有更严格的错误检查。就跟JSON对象和类对象之间的类比。
5.dateFrame和dataSet的区别
dateSet 就是对dateFrame 的封装
dateSet 在dateFrame的基础上加了数据类型
dataSet是dataFrame 特例
DataFrame=Dataset[Row]
dateSet 拥有dataFrame 的查询优化特性
6.Rdd和dataFrame 相互转化
rdd 转dataFrame 实际就是加上结构信息
先导入隐式转化import spark.implicit._
(a)方法一:普通rdd.toDF(“结构信息”)通过手动加入结构信息转换
//创建普通類型rdd
val rdd1: RDD[(Int, String, Int)] = spark.sparkContext.makeRDD(
List(
(1, "zhangsan", 20),
(2, "lisi", 22),
(3, "wangwu", 33))
)
//rdd 转换为dataFrame,手动加入结构信息
import spark.implicits._
val df1: DataFrame = rdd1.toDF("id", "name", "age")
(b)方法二:反射确定(需要用到样例类)
//创建普通類型rdd
val rdd1: RDD[(Int, String, Int)] = spark.sparkContext.makeRDD(
List(
(1, "zhangsan", 20),
(2, "lisi", 22),
(3, "wangwu", 33))
)
//普通rdd转变为caseClass类rdd即RDD[People]
val peopleRdd: RDD[People] = rdd1.map {
case item => {
val p = People(item._1, item._2, item._3)
p
}
}
//样例类rdd因为已经有了结构信息,可以直接转为dataFrame
import spark.implicits._
val df2 = peopleRdd.toDF()
dataFrame 转换为普通Rdd就比较简单了直接去掉结构信息就行了,但是转换不回原来结构,直接转为RDD[row]类型了
//创建普通類型rdd
val rdd: RDD[(Int, String, Int)] = spark.sparkContext.makeRDD(
List(
(1, "zhangsan", 20),
(2, "lisi", 22),
(3, "wangwu", 33))
)
//rdd 转换为dataFrame,手动加入结构信息
import spark.implicits._
val df1: DataFrame = rdd.toDF("id", "name", "age")
//dataFrame转换为rdd
val rdd1: RDD[Row] = df1.rdd
//创建普通類型rdd
val rdd: RDD[(Int, String, Int)] = spark.sparkContext.makeRDD(
List(
(1, "zhangsan", 20),
(2, "lisi", 22),
(3, "wangwu", 33))
)
//普通rdd改编为caseClass类rdd
val peopleRdd: RDD[People] = rdd1.map {
case item => {
val p = People(item._1, item._2, item._3)
p
}
}
//caseClass类型Rdd 因为有结构信息了,直接可以转换了
import spark.implicits._
val df2 : DataFrame= peopleRdd.toDF()
//dataFrame转换为rdd
val rdd2: RDD[Row] = df2.rdd
这里的row是scala的类,可以直接通过角标获取里面值
这里演示以下
/创建普通類型rdd
val rdd: RDD[(Int, String, Int)] = spark.sparkContext.makeRDD(
List(
(1, "zhangsan", 20),
(2, "lisi", 22),
(3, "wangwu", 33))
)
//rdd 转换为dataFrame,手动加入结构信息
import spark.implicits._
val df1: DataFrame = rdd.toDF("id", "name", "age")
//dataFrame转换为rdd
val rdd1: RDD[Row] = df1.rdd
//获取row 里面值
val rowRdd: RDD[(Int, String, Int)] = rdd1.map {
case row =>
//0,1,2 理解为角标
val id: Int = row.getInt(0)
val name: String = row.getString(1)
val age: Int = row.getInt(2)
(id, name, age)
}
//(2,lisi,22)
//(3,wangwu,33)
//(1,zhangsan,20)
rowRdd.foreach(println(_))
这里也可以使用row.getAs[列明]来获取
//创建普通類型rdd
val rdd: RDD[(Int, String, Int)] = spark.sparkContext.makeRDD(
List(
(1, "zhangsan", 20),
(2, "lisi", 22),
(3, "wangwu", 33))
)
//rdd 转换为dataFrame,手动加入结构信息
import spark.implicits._
val df1: DataFrame = rdd.toDF("id", "name", "age")
//dataFrame转换为rdd
val rdd1: RDD[Row] = df1.rdd
val rowRdd2: RDD[(Int, String, Int)] = rdd1.map {
case row =>
val id: Int = row.getAs[Int]("id")
val name: String = row.getAs[String]("name")
val age: Int = row.getAs[Int]("age")
(id, name, age)
}
//(2,lisi,22)
//(3,wangwu,33)
//(1,zhangsan,20)
rowRdd2.foreach(println(_))
6.Rdd和dataSet 相互转化
SparkSQL能够自动将包含有case类的RDD转换成DataFrame,case类定义了table的结构,case类属性通过反射变成了表的列名。
dataSet 就是在Rdd基础上加了结构,加了类型
//创建普通rdd
scala>val peopleRDD = sc.textFile("in")
//创建case class
scala>case class Person(name: String, age: Long)
//RDD[Person]直接转换为Ds
scala>peopleRDD.map(line => {val para = line.split(",");Person(para(0),para(1).trim.toInt)}).toDS()
dataSet转换为Rdd
//创建一个DataSet
scala> val DS = Seq(Person("Andy", 32)).toDS()
DS: org.apache.spark.sql.Dataset[Person] = [name: string, age: bigint]
//将DataSet转换为RDD 转换回的rdd为RDD[Person] 这点
//和dataFame 是有区别的
scala> DS.rdd
res11: org.apache.spark.rdd.RDD[Person] = MapPartitionsRDD[15] at rdd at :28
7.dataFrame和dataSet 相互转化
DataFrame转换为DataSet
1)创建一个DateFrame
scala> val df = spark.read.json("/root/a.json")
df: org.apache.spark.sql.DataFrame = [age: bigint, name: string]
2)创建一个样例类
scala> case class Person(name: String, age: Long)
defined class Person
3)将DateFrame转化为DataSet,相当于
//使用As进行转化
scala> df.as[Person]
res14: org.apache.spark.sql.Dataset[Person] = [age: bigint, name: string]
DataSet转换为DataFrame
1)创建一个样例类
scala> case class Person(name: String, age: Long)
defined class Person
2)创建DataSet
scala> val ds = Seq(Person("Andy", 32)).toDS()
ds: org.apache.spark.sql.Dataset[Person] = [name: string, age: bigint]
3)将DataSet转化为DataFrame
cala> val df = ds.toDF
df: org.apache.spark.sql.DataFrame = [name: string, age: bigint]
4)展示
scala> df.show
+----+---+
|name|age|
+----+---+
|Andy| 32|
+----+---+
8.Rdd,dataFrame,dataSet的共性,区别
ing