RDD、Dataset、DataFrame-对比分析+相互转化

RDD、Dataset、DataFrame 相互转换

1.三者之间好既有区别,也有联系

优点缺点
RDD(关注数据本身)1.内置很多函数操作,group,map,filter 等,方便处理结构化或非结构化数据
2.面向对象编程,直接存储的 java 对象,类型转化也安全
1.由于它基本和 hadoop 一样万能的,因此没有针对特殊场景的优化,比如对于结构化数据处理相对于 sql 来比非常麻烦
2.默认采用的是 java 序列号方式,序列化结果比较大,而且数据存储在 java 堆内存中,导致 gc 比较频繁
DataFrame(关注数据的结构与类型)1.结构化数据处理非常方便,支持 Avro, CSV, elastic search, and Cassandra 等 kv 数据,也支持HIVE tables, MySQL 等传统数据表
2.有针对性的优化,由于数据结构元信息 spark已经保存,序列化时不需要带上元信息,大大的减少了序列化大小,而且数据保存在堆外内存中,减少了 gc 次数
3.hive 兼容,支持 hql,udf 等
1.编译时不能类型转化安全检查,运行时才能确定是否有问题
2.对于对象支持不友好,rdd 内部数据直接以 java 对象存储,DataFrame 内存存储的是 row 对象而不能是自定义对象
DataSet(关注数据(对象))1.Dataset 整合了 RDD 和 DataFrame 的优点,支持结构化和非结构化数据
2.和 RDD 一样,支持自定义对象存储
3.和 DataFrame 一样,支持结构化数据的 sql查询
4.采用堆外内存存储,gc 友好
5.类型转化安全,代码友好
很多情况下,Dataset 的性能实际上是会比 DataFrame 要来得差的,因为 Dataset 会涉及到额外的数据格式转换成本很多情况下,Dataset 的性能实际上是会比 DataFrame 要来得差的,因为 Dataset 会涉及到额外的数据格式转换成本

2.如何转化

1.RDD -> Dataset

val ds = rdd.toDS()

import org.apache.spark.sql.SparkSession

object CreateDataSetDemo {
    //提前准备好样例类
  case class Point(label:String,x:Double,y:Double)
  case class Category(id:Long,name:String)

  def main(args: Array[String]): Unit = {
    //todo:创建sparksession对象
    val spark = SparkSession.builder()
      .appName("test").master("local[*]")
      .getOrCreate()
    val sc = spark.sparkContext

    //todo:导包
    import spark.implicits._

    //todo:创建rdd
    val pointRDD = sc.makeRDD(List(("bar",3.0,4.0),("foo",2.0,2.5)))

    //方法一:
    //todo:使用spark对象直接toDataSet
    val ds1 = pointRDD.toDS()
    
    //方法二:
    //todo;通过样例类创建DataSet
    val pointDS = pointRDD.map(x=>Point(x._1,x._2,x._3)).toDS()

    //todo:分区创建基本相同
    val pointsRDD=sc.parallelize(List(("bar",3.0,5.6),("foo",-1.0,3.0)))
    val categoriesRDD=sc.parallelize(List((1,"foo"),(2,"bar")))
    val pointsDS=pointsRDD.map(line=>Point(line._1,line._2,line._3)).toDS
    val categoriesDS=categoriesRDD.map(line=>Category(line._1,line._2)).toDS
    //todo:两者join
    pointsDS.join(categoriesDS,pointsDS("label")===categoriesDS("name")).show

  }
}

2.RDD -> DataFrame

val df=rdd.toDF()

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.types._
import org.apache.spark.sql.Row

object newDataFrame {
  def main(args: Array[String]): Unit = {
    //todo:创建sparksession对象
    val spark = SparkSession.builder()
      .appName("test").master("local[*]")
      .getOrCreate()
    val sc = spark.sparkContext

    //todo:导包(toDF需要)
    import spark.implicits._

    val rdd1 = sc.parallelize(List(
      ("zhangsan","green",Array(3,5,6,8)),
      ("zhangsan",null,Array(3,5,6,10)),
      ("lisi","red",Array(3,5,6,33)),
      ("zhangsna2","green",Array(3,5,233,9)),
      ("zhangsan","green",Array(3,42,44,9))
    ))

    //todo:方法一:
    val DF1 = rdd1.toDF("name","color","numbers")

    //todo:方法二:
    val schema = StructType(Array(
      StructField("name", StringType, true),
      StructField("color", StringType, true),
      StructField("numbers", ArrayType(IntegerType), true)
    ))
    val rdd2 = rdd1.map(x=>Row(x._1,x._2,x._3))
    val DF2 = spark.createDataFrame(rdd2,schema)
    
    DF1.show()
    DF2.show()
  }
}

3.Dataset -> RDD

val rdd = ds.rdd

4.Dataset -> DataFrame

val df = ds.toDF()

import org.apache.spark.sql.SparkSession

object DS2DF {
  case class Point(label:String,x:Double,y:Double)

  def main(args: Array[String]): Unit = {
    //todo:创建sparksession对象
    val spark = SparkSession.builder()
      .appName("test").master("local[*]")
      .getOrCreate()
    val sc = spark.sparkContext

    //todo:导包
    import spark.implicits._

    //todo:创建rdd
    val pointRDD = sc.makeRDD(List(("bar",3.0,4.0),("foo",2.0,2.5)))

    //todo;通过样例类创建DataSet
    val pointDS = pointRDD.map(x=>Point(x._1,x._2,x._3)).toDS()

    //todo:DS转DF
    val pointDF = pointDS.toDF("label","X","Y")

    pointDF.show()
  }
}

5.DataFrame -> RDD

val rdd = df.rdd

6.DataFrame -> Dataset

val ds = df.toJSON

val ds = df.as[T]

import org.apache.spark.sql.SparkSession

object DF2DS {
  case class Person(name:String,color:String,number:Array[Int])
  def main(args: Array[String]): Unit = {
    //todo:创建sparksession对象
    val spark = SparkSession.builder()
      .appName("test").master("local[*]")
      .getOrCreate()
    val sc = spark.sparkContext

    //todo:导包
    import spark.implicits._

    val rdd1 = sc.parallelize(List(
      ("zhangsan","green",Array(3,5,6,8)),
      ("zhangsan",null,Array(3,5,6,10)),
      ("lisi","red",Array(3,5,6,33)),
      ("zhangsna2","green",Array(3,5,233,9)),
      ("zhangsan","green",Array(3,42,44,9))
    ))

    //todo:生成DF
    val DF1 = rdd1.toDF("name","color","numbers")

    //方法一:tojson
    val DS1 = DF1.toJSON

    //方法二:as【T】
    val DS2 = DF1.as[Person]

    DS1.show()
    DS2.show()
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值