Spark Dataset 入门详解

定义

class Dataset[T](sparkSession: SparkSession, queryExecution: QueryExecution, encoder: Encoder[T])
extends Serializable

数据集是特定于域的对象的强类型集合,可以使用函数或关系操作并行转换这些对象。每个数据集还有一个称为DataFrame的非类型化视图,它是Row的数据集。

数据集上可用的操作分为转换和操作。转换是生成新数据集的转换,而操作是触发计算并返回结果的操作。示例转换包括map、filter、select和aggregate(groupBy)。示例操作计数、显示或将数据写入文件系统。

数据集是“惰性”的,也就是说,只有在调用操作时才会触发计算。在内部,数据集表示一个逻辑计划,该计划描述生成数据所需的计算。当一个动作被调用时,Spark的查询优化器会优化逻辑计划并生成一个物理计划,以便以并行和分布式的方式高效地执行。要探索逻辑计划和优化的物理计划,请使用解释功能。

为了有效地支持特定于域的对象,需要一个编码器。编码器将域特定的类型T映射到Spark的内部类型系统。例如,给定一个具有两个字段name(string)和age(int)的Person类,编码器将用于告诉Spark在运行时生成代码,以将Person对象序列化为二进制结构。这种二进制结构通常具有较低的内存占用,并且针对数据处理的效率进行了优化(例如,以列格式)。要理解数据的内部二进制表示,请使用schema函数。

利用List,Seq,Array创建Dataset 对象

在创建Dataset的时候,需要注意数据的格式,必须使用case class,或者基本数据类型,同时需要通过import spark.implicts._来完成数据类型的编码,而抽取出对应的元数据信息,否则编译无法通过

def createDataset[T : Encoder](data: Seq[T]): Dataset[T]
object DataSetDemo1 extends App {
  val spark: SparkSession = SparkSession.builder()
    .appName("SparkSQL")
    .master("local")
    .getOrCreate()

  import spark.implicits._

  private val girls = List(
  //因为是case class,所以可以不用new关键字构建对象
    Girl(1, "lw", 1, 180.0),
    Girl(2, "wsw", 2, 179.0),
    Girl(3, "chh", 1, 183.0),
    Girl(4, "mnn", 0, 168.0)
  )

  val frame= spark.createDataset(girls)
  frame.show()
  spark.stop()

}
//创建case class
case class Girl(id: Int, name: String, sex: Int, height: Double)

运行结果如下

+---+----+---+------+
| id|name|sex|height|
+---+----+---+------+
|  1|  lw|  1| 180.0|
|  2| wsw|  2| 179.0|
|  3| chh|  1| 183.0|
|  4| mnn|  0| 168.0|
+---+----+---+------+

其中createDataset() 方法传入List,Array,Seq均可.

private val girls = Seq(
    Girl(1, "lw", 1, 180.0),
    Girl(2, "wsw", 2, 179.0),
    Girl(3, "chh", 1, 183.0),
    Girl(4, "mnn", 0, 168.0)
  )

再比如

val ds= spark.createDataset(0 to 10)
ds.show()

运行结果如下

+-----+
|value|
+-----+
|    0|
|    1|
|    2|
|    3|
|    4|
|    5|
|    6|
|    7|
|    8|
|    9|
|   10|
+-----+

利用RDD创建DataSet对象

相当于把上面例子中的List,Array,Seq用RDD包装一下

object rdd2DataSet extends App {
  val spark: SparkSession = SparkSession.builder()
    .appName("SparkSQL")
    .master("local")
    .getOrCreate()

  import spark.implicits._

  private val value: RDD[Girl] = spark.sparkContext.parallelize(List(
    Girl(1, "lw", 1, 180.0),
    Girl(2, "wsw", 2, 179.0),
    Girl(3, "mhh", 1, 183.0),
    Girl(4, "mnn", 0, 168.0)
  ))
  //rdd转dataset
  //Creates a Dataset from an RDD of a given type.
  private val dataset: Dataset[Girl] = spark.createDataset(value)
  dataset.show()
}

其中,RDD转DS还有简便写法,直接调用toDS方法就可以.

  private val dataset: Dataset[Girl] = value.toDS()
  dataset.show()

Dataset转RDD

接上述

  private val rdd: RDD[Girl] = dataset.rdd
  rdd.foreach(println)

运行结果

Girl(1,lw,1,180.0)
Girl(2,wsw,2,179.0)
Girl(3,chh,1,183.0)
Girl(4,mnn,0,168.0)

Dataset转DataFrame

由于type DataFrame = Dataset[Row]. 因此ds转df也就是改个泛型的事情.

 private val dataFrame: DataFrame = dataset.toDF()
  dataFrame.show()

来看一把源码,就是改了Dataset的泛型而已.

def toDF(): DataFrame = new Dataset[Row](sparkSession, queryExecution, RowEncoder(schema))

总结

  • dataset可通过Seq创建,也可以通过RDD创建
  • dataset可以和DataFrame和RDD相互转换
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值