优点:
缺点:
package rdddataframadataset
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
/**
* Created by Administrator on 2017/3/15.
*/
object RddTest {
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("test").setMaster("local")
val sc = new SparkContext(conf)
sc.setLogLevel("WARN")
val sqlContext = new SQLContext(sc)
/**
* id age
* 1 30
* 2 29
* 3 21
*/
case class Person(id: Int, age: Int)
val idAgeRDDPerson = sc.parallelize(Array(Person(1, 30), Person(2, 29), Person(3, 21)))
// 优点1
// idAge.filter(_.age > "") // 编译时报错, int不能跟String比
// 优点2
idAgeRDDPerson.filter(_.age > 25) // 直接操作一个个的person对象
}
}
优点:
缺点:
DataFrame引入了schema和off-heap
package rdddataframadataset
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.{Row, SQLContext}
import org.apache.spark.sql.types.{DataTypes, StructField, StructType}
/**
* Created by Administrator on 2017/3/15.
*/
object DataFrameTest {
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("test").setMaster("local")
val sc = new SparkContext(conf)
sc.setLogLevel("WARN")
val sqlContext = new SQLContext(sc)
/**
* id age
* 1 30
* 2 29
* 3 21
*/
val idAgeRDDRow = sc.parallelize(Array(Row(1, 30), Row(2, 29), Row(4, 21)))
val schema = StructType(Array(StructField("id", DataTypes.IntegerType), StructField("age", DataTypes.IntegerType)))
val idAgeDF = sqlContext.createDataFrame(idAgeRDDRow, schema)
// API不是面向对象的
idAgeDF.filter(idAgeDF.col("age") > 25).show()
// 不会报错, DataFrame不是编译时类型安全的
idAgeDF.filter(idAgeDF.col("age") > "").show()
}
}
ps:DataSet 1.6.0 版本才有
优点:
DataSet结合了RDD和DataFrame的优点, 并带来的一个新的概念Encoder当序列化数据时, Encoder产生字节码与off-heap进行交互, 能够达到按需访问数据的效果,而不用反序列化整个对象. Spark还没有提供自定义Encoder的API, 但是未来会加入.
package rdddataframadataset
import org.apache.spark.sql.types.{DataTypes, StructField, StructType}
import org.apache.spark.sql.{Row, SQLContext}
import org.apache.spark.{SparkConf, SparkContext}
/**
* Created by Administrator on 2017/3/15.
*/
//定义的class 必须放在类的外面,填坑,不知道为什么
case class Persons(name: String, age: Long)
object DataSetTest {
def main(args: Array[String]) {
val conf = new SparkConf().setAppName("test").setMaster("local")
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
import sqlContext.implicits._
// 目前支持String, Integer, Long等类型直接创建Dataset
//Creating Datasets
//第一种
Seq(1, 2, 3).toDS().show()
//第二种
val ds = Seq(Persons("Andy", 32)).toDS()
ds.show()
//第三种
val idAgeRDDRow = sc.parallelize(Array(Row(1, 30), Row(2, 29), Row(4, 21)))
val schema = StructType(Array(StructField("id", DataTypes.IntegerType), StructField("age", DataTypes.IntegerType)))
// 在2.0.0-preview中这行代码创建出的DataFrame, 其实是DataSet[Row]
val idAgeDS = sqlContext.createDataFrame(idAgeRDDRow, schema)
idAgeDS.show()
//第四种
import sqlContext.implicits._ //隐式函数
/* 1.序列化
2. 序列化成对象,调用对象属性*/
val PersionDF = sqlContext.read.json("d://SparkProject//demo1//testdata//person.json").as[Persons]
PersionDF.show()
//第五种
sqlContext.createDataset(sc.parallelize(Array(1, 2, 3))).show()
}
}
总结:
1、RDD支持面向java、scala对象,编译时强类型检查。缺点,序列化非常消耗时间(集群分发和磁盘存储),不能充分利用系统的高级优化能力(如off-heap),垃圾回收对象开销大。
2、DataFrame支持数据集的模式表示(即数据列的概念),所以集群分发数据时并不需要序列化,能充分利用系统高级优化能力(off-heap),引入查询计划提高性能。缺点,DataFrame的列类型,在编译时无法判断类型,会产生运行时错误。
3、Dataset即支持数据集的模式表示,又支持java、scala对象的类型检查能力。两者通过引入一种编码、解码机制来实现。