参赛话题:Spark实战经验分享
目录
简介
1、诞生顺序
RDD | Spark1.0 |
DataFram | Spark1.3 |
DataSet | Spark1.6 |
2、三者之间的转化
理论基础
(一)概念
- RDD
RDD是一种弹性分布式数据集,是Spark中最基本的数据抽象。RDD是只读的记录分区的集合,只能通过在其他RDD执行确定的转换操作(如map、join和group by)而创建,然而这些限制使得实现容错的开销很低。RDD的每一个分区对应就是一个Task线程。
- DataFram
DataFrame是一种分布式的数据集,并且以列的方式组合的。类似于关系型数据库中的表。可以说是一个具有良好优化技术的关系表。DataFrame背后的思想是允许处理大量结构化数据。提供了一些抽象的操作,如select、filter、aggregation、plot。DataFrame包含带schema的行。schema是数据结构的说明。相当于具有schema的RDD。
- DataSet
DataSet是可以并行使用函数或关系操作转化特定域对象的强类型集合。每个DataSet有一个非类型化的DataFram。DataFram是DataSet[Row]的别名。
(二)区别
- DataFram与RDD的主要区别在于,前者带有Schema元信息,即DataFram表示的二维表数据集的每一列都带有名称和类型。这使得Spark SQL 得以解析到具体数据的结构信息,从而对DataFram中的数据源以及对DataFram的操作进行了非常有效的优化,从而大幅提升了运行效率。RDD一般和Spark MLlib同时使用。
- 与DataFram不同的是,DataSet是强类型的,而DataFram实际上就是DataSet[Row](也就是java中的DataSet<Row>)。
(三)共同点
三者都是弹性分布式数据集,都有分区的概念和惰性机制,在进行创建、转换操作时不会立即执行,只有在遇到执行算子时,才会开始执行计算。
实践应用
-
创建case类
case class User(name: String, age: Int, address: String)
-
创建dataFram
val spark = SparkSession.builder().master("local[*]")
.appName("test").getOrCreate()
import spark.implicits._
val sc = spark.sparkContext
sc.setLogLevel("WARN")
/**
* 创建DataFram
*/
val user_df: DataFrame = Seq(
User("zhangsan", 20, "河南"),
User("lisi", 16, "北京"),
User("wangwu", 21, "上海")
).toDF()
val user_rdd: RDD[Row] = user_df.rdd
-
dataFram转dataSet
val user_dataset: Dataset[User] = user_df.as[User]
-
rdd转dataFram
val rddTodf: DataFrame = user_rdd.map(row => {
(row.getAs[String](0), row.getAs[Int](1), row.getAs[String](2))
}).toDF("name1", "age1", "address1")
-
rdd转化为dataSet
val rddToDs: Dataset[User] = user_rdd.map(row => {
User(row.getAs[String](0), row.getAs[Int](1), row.getAs[String](2))
}).toDS()
-
dataSet转dataFram
val dsToDf: DataFrame = user_dataset.toDF()
-
dataSet转rdd
val rdd: RDD[User] = user_dataset.rdd
-
行打印比较
user_df.foreach(t => println(t))
[zhangsan,20,河南]
[wangwu,21,上海]
[lisi,16,北京]
user_rdd.foreach(t => println(t))
[lisi,16,北京]
[zhangsan,20,河南]
[wangwu,21,上海]
user_dataset.foreach(t => println(t))
User(zhangsan,20,河南)
User(wangwu,21,上海)
User(lisi,16,北京)