Spark RDD、DataFrame和DataSet的区别
版权声明:本文为博主原创文章,未经博主允许不得转载。
转载请标明出处:小帆的帆的专栏
RDD
优点:
- 编译时类型安全
编译时就能检查出类型错误 - 面向对象的编程风格
直接通过类名点的方式来操作数据
缺点:
- 序列化和反序列化的性能开销
无论是集群间的通信, 还是IO操作都需要对对象的结构和数据进行序列化和反序列化. - GC的性能开销
频繁的创建和销毁对象, 势必会增加GC
import org.apache.spark.sql.SQLContext
import org.apache.spark.{SparkConf, SparkContext}
object Run {
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
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也不是面向对象风格的.
import org.apache.spark.sql.types.{DataTypes, StructField, StructType}
import org.apache.spark.sql.{Row, SQLContext}
import org.apache.spark.{SparkConf, SparkContext}
object Run {
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)
// 不会报错, DataFrame不是编译时类型安全的
idAgeDF.filter(idAgeDF.col("age") > "")
}
}
DataSet
DataSet结合了RDD和DataFrame的优点, 并带来的一个新的概念Encoder
当序列化数据时, Encoder产生字节码与off-heap进行交互, 能够达到按需访问数据的效果, 而不用反序列化整个对象. Spark还没有提供自定义Encoder的API, 但是未来会加入.
下面看DataFrame和DataSet在2.0.0-preview中的实现
下面这段代码, 在1.6.x中创建的是DataFrame
// 上文DataFrame示例中提取出来的
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)
但是同样的代码在2.0.0-preview中, 创建的虽然还叫DataFrame
// sqlContext.createDataFrame(idAgeRDDRow, schema) 方法的实现, 返回值依然是DataFrame
def createDataFrame(rowRDD: RDD[Row], schema: StructType): DataFrame = {
sparkSession.createDataFrame(rowRDD, schema)
}
但是其实却是DataSet, 因为DataFrame被声明为Dataset[Row]
package object sql {
// ...省略了不相关的代码
type DataFrame = Dataset[Row]
}
因此当我们从1.6.x迁移到2.0.0的时候, 无需任何修改就直接用上了DataSet.
下面是一段DataSet的示例代码
import org.apache.spark.sql.types.{DataTypes, StructField, StructType}
import org.apache.spark.sql.{Row, SQLContext}
import org.apache.spark.{SparkConf, SparkContext}
object Test {
def main(args: Array[String]) {
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)
// 在2.0.0-preview中, 还不支持自定的Encoder, Row类型不行, 自定义的bean也不行
// 官方文档也有写通过bean创建Dataset的例子,但是我运行时并不能成功
// 所以目前需要用创建DataFrame的方法, 来创建DataSet[Row]
// sqlContext.createDataset(idAgeRDDRow)
// 目前支持String, Integer, Long等类型直接创建Dataset
Seq(1, 2, 3).toDS().show()
sqlContext.createDataset(sc.parallelize(Array(1, 2, 3))).show()
}
}
参考
Introducing Apache Spark Datasets
APACHE SPARK: RDD, DATAFRAME OR DATASET?
RDD、DataFrame和DataSet的区别
Spark 2.0.0-preview 官方文档
Spark RDD、DataFrame和DataSet的区别的更多相关文章
- RDD、DataFrame和DataSet的区别
原文链接:http://www.jianshu.com/p/c0181667daa0 RDD.DataFrame和DataSet是容易产生混淆的概念,必须对其相互之间对比,才可以知道其中异同. RDD ...
- 谈谈RDD、DataFrame、Dataset的区别和各自的优势
在spark中,RDD.DataFrame.Dataset是最常用的数据类型,本博文给出笔者在使用的过程中体会到的区别和各自的优势 共性: 1.RDD.DataFrame.Dataset全都是spar ...
- RDD, DataFrame or Dataset
总结: 1.RDD是一个Java对象的集合.RDD的优点是更面向对象,代码更容易理解.但在需要在集群中传输数据时需要为每个对象保留数据及结构信息,这会导致数据的冗余,同时这会导致大量的GC. 2.Da ...
- spark第七篇:Spark SQL, DataFrame and Dataset Guide
预览 Spark SQL是用来处理结构化数据的Spark模块.有几种与Spark SQL进行交互的方式,包括SQL和Dataset API. 本指南中的所有例子都可以在spark-shell,pysp ...
- Spark RDD(Resilient Distributed Dataset)
基于数据集的处理:从物理存储上加载数据,然后操作数据,然后写入物理存储设备.比如Hadoop的MapReduce. 缺点:1.不适合大量的迭代 2. 交互式查询 3. 不能复用曾经的 ...
- spark结构化数据处理:Spark SQL、DataFrame和Dataset
本文讲解Spark的结构化数据处理,主要包括:Spark SQL.DataFrame.Dataset以及Spark SQL服务等相关内容.本文主要讲解Spark 1.6.x的结构化数据处理相关东东,但 ...
- Spark学习之路(八)—— Spark SQL 之 DataFrame和Dataset
一.Spark SQL简介 Spark SQL是Spark中的一个子模块,主要用于操作结构化数据.它具有以下特点: 能够将SQL查询与Spark程序无缝混合,允许您使用SQL或DataFrame AP ...
- Spark 系列(八)—— Spark SQL 之 DataFrame 和 Dataset
一.Spark SQL简介 Spark SQL 是 Spark 中的一个子模块,主要用于操作结构化数据.它具有以下特点: 能够将 SQL 查询与 Spark 程序无缝混合,允许您使用 SQL 或 Da ...
- spark的数据结构 RDD——DataFrame——DataSet区别
转载自:http://blog.csdn.net/wo334499/article/details/51689549 RDD 优点: 编译时类型安全 编译时就能检查出类型错误 面向对象的编程风格 直接 ...
随机推荐
- Apache+Tomcat负载均衡集群搭建
1.所需软件 apache_2.2.4-win32-x86-no_ssl.apacheserver mod_jk-apache-2.2.4连接器,连接apache和tomcat apache-tomc ...
- mac安装热更新插件
查看.修改或者执行某些命令需要root用户的权限,如果不想直接切换到root用户,就可以使用sudo命令.sudo命令用于针对单个命令授予临时权限.sudo仅在需要时授予用户权限,减少了用户因为错误执 ...
- 用Python读取大文件
通常我们在读取文件的时候,会用到read(), readline(), readlines(). 通常可能会有这样的用法: def test1(): with open("/tmp/test ...
- vue 通信方式汇总
1.10种通信方式 10种:https://juejin.im/post/5bd18c72e51d455e3f6e4334 2.除此之外,还有children和ref. 需要注意 $children ...
- vue Watcher分类 computed watch
1.Watcher构造函数源码部分代码 if (options) { this.deep = !!options.deep this.user = !!options.user this.lazy = ...
- hadoop的namenode无法启动的解决的方法
安装hadoop集群时,启动集群,发现master节点的namenode没有启动成功.这一般都是没有格式格式化namenode的缘故.格式化一下就可以,格式化namenode的命令:在hadoop安装 ...
- leetcode || 58、Length of Last Word
problem: Given a string s consists of upper/lower-case alphabets and empty space characters ' ', ret ...
- 使用ShareSDK完成第三方(QQ、微信、微博)登录和分享
这几天遇到一个需求:做第三方登录和分享.遇到了一些坑,把整个过程整理记录下来,方便他人,同时也捋一下思路. 当时考虑过把每个平台的SDK下载下来,一个一个弄,一番取舍后决定还是用ShareSDK.这里 ...
- iOS - 跑马灯、弹幕
1.跑马灯 具体实现代码见 GitHub 源码 QExtension QMarqueeView.h #pragma mark - QMarqueeViewDelegate /// 跑马灯内容点击处理协 ...
- 【Linux】在线求助man page与info page
先来了解一下Linux有多少命令呢?在文本模式下,你可以直接按下两个[Tab]按键,看看总共有多少命令可以让你用? [knife@www ~]$ <==在这里不要输入任何字符,直接输入两次[ta ...