Spark RDD、DataFrame和DataSet的区别

Spark RDD、DataFrame和DataSet的区别

在比较这三者的区别之前,先看看他们各自的定义是什么。

Spark RDD
RDD是一种弹性分布式数据集,是一种只读分区数据。它是spark的基础数据结构,具有内存计算能力、数据容错性以及数据不可修改特性。

Spark Dataframe
Dataframe也是一种不可修改的分布式数据集合,它可以按列查询数据,类似于关系数据库里面的表结构。可以对数据指定数据模式(schema)。

Spark Dataset
Dataset是DataFrame的扩展,它提供了类型安全,面向对象的编程接口。也就是说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=0val test=rdd.map{line=>println("运行")flag+=1println(flag)line._1}
println(test.count)
println(flag)/**运行1运行2运行330* */*

不使用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)col1case _=>""}

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

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

区别

RDD

1、RDD一般和spark mlib同时使用
2、RDD不支持sparksql操作
rdd dataframe
上图直观地体现了DataFrame和RDD的区别。左侧的RDD[Person]虽然以Person为类型参数,但Spark框架本身不了解 Person类的内部结构。而右侧的DataFrame却提供了详细的结构信息,使得Spark SQL可以清楚地知道该数据集中包含哪些列,每列的名称和类型各是什么。DataFrame多了数据的结构信息,即schema。RDD是分布式的 Java对象的集合。DataFrame是分布式的Row对象的集合。Dataset可以认为是DataFrame的一个特例,主要区别是Dataset每一个record存储的是一个强类型值而不是一个Row。

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同时使用。

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

3、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.rddval 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._ 不然toDFtoDS无法使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/772998.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[CISCN2019 华东北赛区]Web2

[CISCN2019 华东北赛区]Web2 随便注册一个登录,发现 还有反馈页面,一看就知道大概率是xss,应该是为了得到管理员cookie扫描了一下,果然有admin.php后台登录 buu可以连接访问外网了,所以内部的xss平台关闭了&#xff0…

静态住宅IP好用吗?怎么选择?

在进行海外 IP 代理时,了解动态住宅 IP 和静态住宅 IP 的区别以及如何选择合适的类型非常重要。本文将介绍精态住宅 IP 特点和,并提供选择建议,帮助您根据需求做出明智的决策。 静态住宅 IP 的特点 静态住宅 IP 是指 IP 地址在一段时间内保…

深度理解文件操作

目录 文件 文件名: 标准流 文件指针 文件的打开和关闭 文件的顺序读写: 使用部分 文件的打开和关闭 文件 文件分两种,第一种是程序文件,后一种是数据文件。 程序文件:包括源程序文件(后缀为.c&…

如何使用WordPress插件保护网站的安全

前段时间我们的网站受到了黑客的攻击,网站丢失了一些重要的数据,为了防止这种情况的再次发生,我们准备将网站全部迁移到高防服务器,经过一番对比后,我们选择了Hostease提供的高防服务器。它可以有效地抵御各种类型的网…

银行单元化架构体系介绍

1.背景 自2018年以来,受“华为、中兴事件”影响,我国科技受制于人的现状对国家稳定和经济发展都提出了严峻考验。目前我国IT架构体系严重依赖国外产品,金融行业尤其明显。大部分传统银行的关键账务系统都架设在IBM的大型机、小型机之上&…

【jenkins+cmake+svn管理c++项目】创建一个项目

工作台点击"新建item",进入下图,选择Freestyle project,并输入项目名称, 点击确定之后进入项目配置页面,填写描述,然后在下边源码管理部分选择svn, 填写代码的url 上图的Credentials处填写svn的有效登录名和密码&#x…

VMware虚拟机中的Ubuntu Samba映射Windows10文件夹

sudo apt-get install samba安装Samba mkdir share创建共享文件夹 sudo vim /etc/samba/smb.conf编辑配置文件 [share]comment VMware Ubuntu Sharepath /home/zhu/share browseable yeswritable yescreate mask 777comment 是简介 path 是共享文件夹的路径&#xff0c…

【MATLAB源码-第15期】基于matlab的MSK的理论误码率与实际误码率BER对比仿真,采用差分编码和IQ调制解调。

操作环境: MATLAB 2022a 1、算法描述 在数字调制中,最小频移键控(Minimum-Shift Keying,缩写:MSK)是一种连续相位调制的频移键控方式,在1950年代末和1960年代产生。[1] 与偏移四相相移键控&a…

“数字化”持续走热,VR全景助力制造业上“云”

制造业要升级,数字化改造是重要途径。 早年间,由于对数字化的认识不足,一些企业明明有数字化改造需求,却不敢、不愿、不会上“云”。直到此次两会期间,2024年政府工作报告再次提出推动制造业数字化转型,越…

网络——套接字编程TCP

目录 服务端 创建套接字(socket) 服务端绑定(bind) 服务端监听(listen) 服务器接收(accept) 服务端处理(read & write) 客户端 创建套接字&#…

CVE-2022-33891 Apache Spark shell 命令注入漏洞分析

漏洞简介 Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎。Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的类Hadoop MapReduce的通用并行框架 Spark,拥有Hadoop MapReduce所具有的优点;但不同于MapReduce的…

鸿蒙OS开发实例:【demo选择列表限定数量】

效果图: 示例代码 // 使用 DevEco Studio 3.1.1 Release 及以上版本,API 版本为 api 9 及以上。 // 主要功能及注意事项: // 该组件展示了一个乘客选择列表。列表中的每个项目包含一个复选框和对应的乘客姓名, // 用户点击任意一…

MATLAB 自定义生成圆柱点云(49)

MATLAB 自定义生成圆柱点云(49) 一、算法介绍二、具体实现1.代码2.效果一、算法介绍 按照一些提前指定的圆柱参数,自定义生成圆柱点云,可添加噪声,用于后续的实验测试 二、具体实现 1.代码 代码如下(示例): % 指定圆柱的参数 radius = 5; % 圆柱半径 height = 20…

【Spring源码】Bean采用什么数据结构进行存储

一、前瞻 经过上篇源码阅读博客的实践,发现按模块阅读也能获得不少收获,而且能更加系统地阅读源码。 今天的阅读方式还是按模块阅读的方式,以下是Spring各个模块的组成。 那今天就挑Beans这个模块来阅读,先思考下本次阅读的阅读…

Jmeter脚本优化——随机函数

线程组下有 2 个请求的参数中均使用到相同的参数,在进行参数化时,想 要每个请求使用不同的取值。 ( 1 ) 线程组设置如下 ( 2 ) 线程组下添加加购物车请求,请求传参包含商品 id (…

前端日期组件layui使用,月模式

初学前端,实战总结 概要 有一个日期组件,我的谷歌浏览器选完日期后,偶尔获取不到最新数据,有一个客户,是经常出不来数据。 日期组件是Wdate:调用的方法是WdatePicker onpicking,代码片段如下…

基于AT89C51单片机的智能交通灯设计

点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/89035863?spm1001.2014.3001.5503 1绪 论 1.1课题研究背景 交通是城市经济活动的命脉,对城市经济发展、人民生活水平的提高起着十分重要的作用。城市交…

干货分享DS5L1伺服电机通过倍讯科技485转 Profinet 网关与西门子PLC进行通信的配置方法

倍讯科技485转 ProfinetDS5L1 伺服电机与 Profinet 网关进行通信需要了解 Profinet 协议和伺服电机的具体通信要求。以下是您可以如何解决此问题的总体概述: 了解 Profinet:Profinet 是自动化工业以太网标准。您需要了解 Profinet 的工作原理、其寻址方案…

纳斯达克大屏:媒体尺寸及投放费用详解

纳斯达克大屏媒体尺寸及投放费用详解 纳斯达克图片要求 像素 纳斯达克大屏媒体图片的像素要求为2336 H x 1832 W (pixels)。确保你的图片符合这一尺寸要求,以确保在大屏上的显示效果最佳。 分辨率 分辨率要求为(1.0) px 72 dpi。这意味着每个像素显示为一个实…

Spire.PDF for .NET【文档操作】演示:查找并删除 PDF 中的空白页

PDF 中的空白页并不罕见,因为它们可能是作者故意留下的或在操作文档时意外添加的。当您阅读或打印文档时,这些空白页可能会很烦人,因此可能非常有必要将其删除。在本文中,您将了解如何使用Spire.PDF for .NET以编程方式查找和删除…