在spark中,RDD、DataFrame、Dataset是最常用的数据类型,本博文给出笔者在使用的过程中体会到的区别和各自的优势

共性:

1、RDD、DataFrame、Dataset全都是spark平台下的分布式弹性数据集,为处理超大型数据提供便利

2、三者都有惰性机制,在进行创建、转换,如map方法时,不会立即执行,只有在遇到Action如foreach时,三者才会开始遍历运算,极端情况下,如果代码里面有创建、转换,但是后面没有在Action中使用对应的结果,在执行时会被直接跳过,如

val sparkconf = new SparkConf().setMaster("local").setAppName("test").set("spark.port.maxRetries","1000")
val spark = SparkSession.builder().config(sparkconf).getOrCreate()
val rdd=spark.sparkContext.parallelize(Seq(("a", 1), ("b", 1), ("a", 1))) rdd.map{line=>
println("运行")
line._1
}

map中的println("运行")并不会运行

3、三者都会根据spark的内存情况自动缓存运算,这样即使数据量很大,也不用担心会内存溢出

4、三者都有partition的概念,如

 var predata=data.repartition(24).mapPartitions{
PartLine => {
PartLine.map{
line =>
println(“转换操作”)
}
}
}

这样对每一个分区进行操作时,就跟在操作数组一样,不但数据量比较小,而且可以方便的将map中的运算结果拿出来,如果直接用map,map中对外面的操作是无效的,如

val rdd=spark.sparkContext.parallelize(Seq(("a", 1), ("b", 1), ("a", 1)))
var flag=0
val test=rdd.map{line=>
println("运行")
flag+=1
println(flag)
line._1
}
println(test.count)
println(flag)
/**
运行
1
运行
2
运行
3
3
0
* */

不使用partition时,对map之外的操作无法对map之外的变量造成影响

5、三者有许多共同的函数,如filter,排序等

6、在对DataFrame和Dataset进行操作许多操作都需要这个包进行支持

import spark.implicits._
//这里的spark是SparkSession的变量名

7、DataFrame和Dataset均可使用模式匹配获取各个字段的值和类型

DataFrame:

testDF.map{
case Row(col1:String,col2:Int)=>
println(col1);println(col2)
col1
case _=>
""
}

为了提高稳健性,最好后面有一个_通配操作,这里提供了DataFrame一个解析字段的方法

Dataset:

case class Coltest(col1:String,col2:Int)extends Serializable //定义字段名和类型
testDS.map{
case Coltest(col1:String,col2:Int)=>
println(col1);println(col2)
col1
case _=>
""
}

  

区别:

RDD:

1、RDD一般和spark mlib同时使用

2、RDD不支持sparksql操作

DataFrame:

1、与RDD和Dataset不同,DataFrame每一行的类型固定为Row,只有通过解析才能获取各个字段的值,如

testDF.foreach{
line =>
val col1=line.getAs[String]("col1")
val col2=line.getAs[String]("col2")
}

每一列的值没法直接访问

2、DataFrame与Dataset一般与spark ml同时使用

3、DataFrame与Dataset均支持sparksql的操作,比如select,groupby之类,还能注册临时表/视窗,进行sql语句操作,如

dataDF.createOrReplaceTempView("tmp")
spark.sql("select ROW,DATE from tmp where DATE is not null order by DATE").show(100,false)

4、DataFrame与Dataset支持一些特别方便的保存方式,比如保存成csv,可以带上表头,这样每一列的字段名一目了然

//保存
val saveoptions = Map("header" -> "true", "delimiter" -> "\t", "path" -> "hdfs://172.xx.xx.xx:9000/test")
datawDF.write.format("com.databricks.spark.csv").mode(SaveMode.Overwrite).options(saveoptions).save()
//读取
val options = Map("header" -> "true", "delimiter" -> "\t", "path" -> "hdfs://172.xx.xx.xx:9000/test")
val datarDF= spark.read.options(options).format("com.databricks.spark.csv").load()

利用这样的保存方式,可以方便的获得字段名和列的对应,而且分隔符(delimiter)可以自由指定

Dataset:

这里主要对比Dataset和DataFrame,因为Dataset和DataFrame拥有完全相同的成员函数,区别只是每一行的数据类型不同

DataFrame也可以叫Dataset[Row],每一行的类型是Row,不解析,每一行究竟有哪些字段,各个字段又是什么类型都无从得知,只能用上面提到的getAS方法或者共性中的第七条提到的模式匹配拿出特定字段

而Dataset中,每一行是什么类型是不一定的,在自定义了case class之后可以很自由的获得每一行的信息

case class Coltest(col1:String,col2:Int)extends Serializable //定义字段名和类型
/**
rdd
("a", 1)
("b", 1)
("a", 1)
* */
val test: Dataset[Coltest]=rdd.map{line=>
Coltest(line._1,line._2)
}.toDS
test.map{
line=>
println(line.col1)
println(line.col2)
}

可以看出,Dataset在需要访问列中的某个字段时是非常方便的,然而,如果要写一些适配性很强的函数时,如果使用Dataset,行的类型又不确定,可能是各种case class,无法实现适配,这时候用DataFrame即Dataset[Row]就能比较好的解决问题

转化:

RDD、DataFrame、Dataset三者有许多共性,有各自适用的场景常常需要在三者之间转换

DataFrame/Dataset转RDD:

这个转换很简单

val rdd1=testDF.rdd
val rdd2=testDS.rdd

RDD转DataFrame:

import spark.implicits._
val testDF = rdd.map {line=>
(line._1,line._2)
}.toDF("col1","col2")

一般用元组把一行的数据写在一起,然后在toDF中指定字段名

RDD转Dataset:

import spark.implicits._
case class Coltest(col1:String,col2:Int)extends Serializable //定义字段名和类型
val testDS = rdd.map {line=>
Coltest(line._1,line._2)
}.toDS

可以注意到,定义每一行的类型(case class)时,已经给出了字段名和类型,后面只要往case class里面添加值即可

Dataset转DataFrame:

这个也很简单,因为只是把case class封装成Row

import spark.implicits._
val testDF = testDS.toDF

DataFrame转Dataset:

import spark.implicits._
case class Coltest(col1:String,col2:Int)extends Serializable //定义字段名和类型
val testDS = testDF.as[Coltest]

这种方法就是在给出每一列的类型后,使用as方法,转成Dataset,这在数据类型是DataFrame又需要针对各个字段处理时极为方便

特别注意:

在使用一些特殊的操作时,一定要加上 import spark.implicits._ 不然toDF、toDS无法使用

谈谈RDD、DataFrame、Dataset的区别和各自的优势的更多相关文章

  1. sparkSQL中RDD——DataFrame——DataSet的区别

    spark中RDD.DataFrame.DataSet都是spark的数据集合抽象,RDD针对的是一个个对象,但是DF与DS中针对的是一个个Row RDD 优点: 编译时类型安全 编译时就能检查出类型 ...

  2. spark的数据结构 RDD——DataFrame——DataSet区别

    转载自:http://blog.csdn.net/wo334499/article/details/51689549 RDD 优点: 编译时类型安全 编译时就能检查出类型错误 面向对象的编程风格 直接 ...

  3. APACHE SPARK 2.0 API IMPROVEMENTS: RDD, DATAFRAME, DATASET AND SQL

    What’s New, What’s Changed and How to get Started. Are you ready for Apache Spark 2.0? If you are ju ...

  4. spark rdd df dataset

    RDD.DataFrame.DataSet的区别和联系 共性: 1)都是spark中得弹性分布式数据集,轻量级 2)都是惰性机制,延迟计算 3)根据内存情况,自动缓存,加快计算速度 4)都有parti ...

  5. RDD, DataFrame or Dataset

    总结: 1.RDD是一个Java对象的集合.RDD的优点是更面向对象,代码更容易理解.但在需要在集群中传输数据时需要为每个对象保留数据及结构信息,这会导致数据的冗余,同时这会导致大量的GC. 2.Da ...

  6. RDD、DataFrame和DataSet的区别

    原文链接:http://www.jianshu.com/p/c0181667daa0 RDD.DataFrame和DataSet是容易产生混淆的概念,必须对其相互之间对比,才可以知道其中异同. RDD ...

  7. Spark RDD、DataFrame和DataSet的区别

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   转载请标明出处:小帆的帆的专栏 RDD 优点: 编译时类型安全 编译时就能检查出类型错误 面向对象的编程风格 直接通过类 ...

  8. Spark入门之DataFrame/DataSet

    目录 Part I. Gentle Overview of Big Data and Spark Overview 1.基本架构 2.基本概念 3.例子(可跳过) Spark工具箱 1.Dataset ...

  9. Data Base sqlServer DataReader与DataSet的区别

    sqlServer   DataReader与DataSet的区别 从以下这几个方面比较: 1.与数据库连接: DataReader:面向连接,只读,只进,只能向前读,读完数据就断开连接: DataS ...

随机推荐

  1. Java开发过程中开发工具Eclipse中导入jar包的过程

    欢迎欣赏我的第二篇随笔.我们在创建好一个动态网站项目之后,如果没有部署maven的情况下,你可以按照以下的方法,直接把要用的jar包导入你的工程中,而不用再部署maven. 例如在使用JDBC编程时需 ...

  2. nicescroll 配置参数

    jQuery滚动条插件兼容ie6+.手机.ipad http://www.areaaperta.com/nicescroll/ 配置参数 当调用“niceScroll”你可以传递一些参数来定制视觉方面 ...

  3. pyqt系列原创入门教程

    pyqt4入门教程 python pyqt4 PyQt是一个创建GUI应用程序的工具包.它是Python编程语言和Qt库的成功融合.Qt库是目前最强大的库之一. 通过pyqt可以实现很多我们想要的功能 ...

  4. 分类算法——k最近邻算法(Python实现)(文末附工程源代码)

    kNN算法原理 k最近邻(k-Nearest Neighbor)算法是比较简单的机器学习算法.它采用测量不同特征值之间的距离方法进行分类,思想很简单:如果一个样本在特征空间中的k个最近邻(最相似)的样 ...

  5. javaScriptCore 实战 与 小结

      源码在这,看不懂的直接撸源码就行,转载声明出处 原生调用JS的大致流程,做了个思维简图 这是代码流程 // JS数据 func getJSVar() { let context: JSContex ...

  6. Unity SteamVR插件集成

    重要组件 SteamVR_Camera VR摄像机,主要功能是将Unity摄像机的画面进行变化,形成Vive中的成像画面 使用方法: l 在任一个摄像机上增加脚本 l 点击Expand按钮 完成以上操 ...

  7. 【C语言】模拟实现printf函数(可变参数)

    一.printf函数介绍 printf功能 printf函数是格式化输出函数,一般用于向标准输出设备按规定格式输出信息. printf原型 int printf( const char* format ...

  8. Nginx+Tomcat动静分离脚本

    #!/bin/bashsetenforce 0systemctl stop firewalldtar -zxvf nginx-1.8.0.tar.gz -C /usr/src/ cd /usr/src ...

  9. RDCの自我介绍

    ........................................... 大家好,这里是RUSH_D_CAT.一只ACMer,19岁的少年,From SDU,大二. Q: 1950499 ...

  10. 我的iOS-App

    1.PocketConfidential(密保箱) 简介 保存账号密码等敏感信息. 应用技术: sqlite.sqlcipher加密.AES数据加密.GCD https://itunes.apple. ...