spark 三种创建 数据集的方法,及测试(Scala代码)

1 通过创建RDD执行查询

/**
  *
  * 优点:
  *
  * 编译时类型安全
  * 编译时就能检查出类型错误
  * 面向对象的编程风格
  * 直接通过类名点的方式来操作数据
  * 缺点:
  *
  * 序列化和反序列化的性能开销
  * 无论是集群间的通信, 还是IO操作都需要对对象的结构和数据进行序列化和反序列化.
  * GC的性能开销
  * 频繁的创建和销毁对象, 势必会增加GC
  */
def rddTest(): Unit ={
  val conf = new SparkConf().setAppName("test").setMaster("local")
  val sc = new SparkContext(conf)
  sc.setLogLevel("WARN")
  val sqlContext = new SQLContext(sc)

  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).take(1000).foreach(println); // 直接操作一个个的person对象
}

2  通过  DataFrame引入了schema和off-heap

**
  *
  * DataFrame引入了schema和off-heap
  *
  * schema : RDD每一行的数据, 结构都是一样的. 这个结构就存储在schema中. Spark通过schame就能够读懂数据, 因此在通信和IO时就只需要序列化和反序列化数据, 而结构的部分就可以省略了.
  *
  * off-heap : 意味着JVM堆以外的内存, 这些内存直接受操作系统管理(而不是JVM)。Spark能够以二进制的形式序列化数据(不包括结构)到off-heap中, 当要操作数据时, 就直接操作off-heap内存. 由于Spark理解schema, 所以知道该如何操作.
  *
  * off-heap就像地盘, schema就像地图, Spark有地图又有自己地盘了, 就可以自己说了算了, 不再受JVM的限制, 也就不再收GC的困扰了.
  *
  * 通过schema和off-heap, DataFrame解决了RDD的缺点, 但是却丢了RDD的优点. DataFrame不是类型安全的, API也不是面向对象风格的.
  */
def dataFrameTest(): Unit ={

  val conf = new SparkConf().setAppName("test").setMaster("local")
  val sc = new SparkContext(conf)
  sc.setLogLevel("WARN")
  val sqlContext = new SQLContext(sc)

  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).take(1000).foreach(println);
  // 不会报错, DataFrame不是编译时类型安全的
  idAgeDF.filter(idAgeDF.col("age") > "").take(1000).foreach(println);
}
3 DataSet结合了RDD和DataFrame的优点, 并带来的一个新的概念Encoder
**
  * DataSet结合了RDD和DataFrame的优点, 并带来的一个新的概念Encoder
  *
  * 当序列化数据时, Encoder产生字节码与off-heap进行交互, 能够达到按需访问数据的效果, 而不用反序列化整个对象. Spark还没有提供自定义Encoder的API, 但是未来会加入.
  *
  * 下面看DataFrame和DataSet在2.0.0-preview中的实现
  */
def dataSetTest(): Unit ={

  val conf = new SparkConf().setAppName("test").setMaster("local") // 调试的时候一定不要用local[*]
  val sc = new SparkContext(conf)
  val sqlContext = new SQLContext(sc)
  import sqlContext.implicits._

  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.registerTempTable("test")

  sqlContext.sql("SELECT * FROM test").show()

  // 在2.0.0-preview中, 还不支持自定的Encoder, Row类型不行, 自定义的bean也不行
  // 官方文档也有写通过bean创建Dataset的例子,但是我运行时并不能成功
  // 所以目前需要用创建DataFrame的方法, 来创建DataSet[Row]
  // sqlContext.createDataset(idAgeRDDRow)

  // 目前支持String, Integer, Long等类型直接创建Dataset
  //Seq(1, 2, 3).toDS().take(1000).foreach(println);
  //sqlContext.createDataset(sc.parallelize(Array(1, 2, 3))).take(1000).foreach(println);
}

4 通过Main 方法调用

def main(args: Array[String]): Unit = { //创建spark的运行环境
  rddTest()
  dataFrameTest()
  dataSetTest()
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值