前言
- SparkContext是RDD的环境
- SparkSession是DataSet和DataFrame的环境,SparkSession内部封装了SparkContext
- StreamingContext是Spark streaming得环境,底层封装了SparkContext
// 创建RDD 得 SparkContext 环境
val sparkConf: SparkConf = new SparkConf().setAppName("haha").setMaster("local[*]")
val sc = new SparkContext(sparkConf)
// 创建 spark sql 环境
val spark: SparkSession = SparkSession.builder().master("local[*]").appName("haha").getOrCreate()
// 创建 Spark streaming 环境
val sparkConf: SparkConf = new SparkConf().setAppName("haha").setMaster("local[*]")
val ssc = new StreamingContext(sparkConf,Seconds(3))
- SparkSql是将SparkSql转换成RDD然后再执行
- SparkSql提供了两个数据抽象:DataSet和DataFrame
共性
RDD
- 使用java序列化,序列化结果比较大,而且数据存储在java对内存中,导致gc比较频繁
- RDD[Person],以person为类型参数,但Spark本身不了解Person的内部结构
- 类型安全,写代码时就可以看出是否出错
val spark: SparkSession = SparkSession.builder().master("local[*]").appName("haha").getOrCreate()
import spark.implicits._
val ssc: SparkContext = spark.sparkContext
val rdd: RDD[(String, Int)] = ssc.makeRDD(Array(("a", 1), ("b", 2)))
rdd.foreach(line => {
println(line._1 + "_" +line._2)
})
DataFrame
- 采用kryo序列化,由于数据辕信息spark已经保存,序列化时不需要带上元信息,序列化的只有数据本身。且数据保存在堆外内存中,较少了gc次数,所以运行更快
- DataFrame提供了详细的结构信息,类似于数据库中的一张表,性能比RDD快,因为经过优化
- 类型不安全
df.foreach{
line=>
// DataFrame每一行的类型固定为Row,只有通过解析才能获取各个字段的值
val col1: Unit = line.getAs[String]("col1")
val col2: String = line.getAs[String]("col2")
// 第二种方法
val col1 : String = line.getString(1)
}
DataSet
- DataSet(1.6才有),和DataFrame一样,使用kryo序列化,采用堆外内存
- 类型安全
- 样例类被用来在DataSet中定义数据的结构信息,样例类中的每个属性的名称直接映射到DataSet中的字段名称
- DaraFrame是DataSet的特例,DataFrame = DataSet[Row],Row是一个类型,可以是Car、Person,或者说样例类。
- DataFrame只知道字段,不知道字段的类型,所以没办法再编译的时候检查是否类型失败的。而DataSet不仅知道字段,还知道类型
object test11 {
def main(args: Array[String]): Unit = {
val spark: SparkSession = SparkSession.builder().master("local[*]").appName("haha").getOrCreate()
import spark.implicits._
val ssc: SparkContext = spark.sparkContext
val rdd: RDD[(String, Int)] = ssc.makeRDD(Array(("a", 1), ("b", 2), ("c", 3)))
val ds: Dataset[Coltest] = rdd.map(line =>
Coltest(line._1, line._2)
).toDS()
ds.map {
line =>
// 可以直接访问 DS 中的字段
println(line.col1)
println(line.col2)
}
}
}
case class Coltest(col1: String, col2: Int) extends Serializable //定义字段名和类型