Spark中RDD、DataFrame和DataSet的区别 ?

今天的三个问题是:

1.Spark1.0和2.0有什么区别?(真心不想重装2.0,但是没有办法啊)

2.Spark RDD、DataFrame和DataSet的区别 ?(往期第33题写过一次,但没有解释清楚)

3.如何选择RDD还是DataFrame/DataSet?


话不多说,直接上干货,最后附上了原文参考文献,觉得有翻译不到位的地方可以看看原文,欢迎各位指出更正。


首先Spark RDD、DataFrameDataSetSpark的三类API,下图是他们的发展过程:

Spark中RDD、DataFrame和DataSet的区别 ?

Spark中RDD、DataFrame和DataSet的区别 ?

DataFramespark1.3.0版本提出来的,spark1.6.0版本又引入了DateSet但是在spark2.0版本中DataFrameDataSet合并为DataSet。

那么你可能会问了那么2.0以后的版本里,RDDs是不是不需要了呢

答案是:NO!首先,DataFrameDataSet是基于RDDs而且这三者之间可以通过简单的API调用进行无缝切换

下面依次介绍这三类API的特点

、RDD

RDD的优点
1.相比于传统的MapReduce框架,SparkRDD中内置很多函数操作,group,map,filter方便处理结构化或非结构化数据
2.面向对象编程直接存储的java对象类型转化也安全

RDD的缺点
1.由于它基本和hadoop一样万能的因此没有针对特殊场景的优化比如对于结构化数据处理相对于sql来比非常麻烦
2.默认采用的是java***方式序列化结果比较大而且数据存储在java堆内存中导致gc比较频繁

Spark中RDD、DataFrame和DataSet的区别 ?

、DataFrame
DataFrame的优点
1.结构化数据处理非常方便支持Avro, CSV, elastic search, and Cassandrakv数据也支持HIVE tables, MySQL等传统数据表

Spark中RDD、DataFrame和DataSet的区别 ?2.有针对性的优化如采用Kryo序列化由于数据结构元信息spark已经保存序列化时不需要带上元信息大大的减少了序列化大小而且数据保存在堆外内存中减少了gc次数,所以运行更快

Spark中RDD、DataFrame和DataSet的区别 ?

3.hive兼容支持hql、udf

DataFrame的缺点
1.编译时不能类型转化安全检查运行时才能确定是否有问题
2.对于对象支持不友好,rdd内部数据直接以java对象存储,dataframe内存存储的是row对象而不能是自定义对象

 

、DateSet

DateSet的优点
1.DateSet整合了RDDDataFrame的优点支持结构化和非结构化数据
2.RDD一样支持自定义对象存储
3.DataFrame一样支持结构化数据的sql查询
4.采用堆外内存存储,gc友好

5.类型转化安全代码友好

、new DateSet

Spark2.0之后DataFrameDataSet合并为更高级的DataSet,新的DataSet具有两个不同的API特性:1.非强类型(untyped),DataSet[Row]是泛型对象的集合它的别名是DataFrame;2.强类型(strongly-typed),DataSet[T]是具体对象的集合scalajava中定义的类

Spark中RDD、DataFrame和DataSet的区别 ?

   因为PythonR没有编译阶段所以只有无类型的API,DataFrame。

1.静态类型和运行时类型安全

例如在用Spark SQL进行查询时直到运行时才会发现(syntax error)语法错误这样成本太高),而采用DataFrameDataSet可以在编译时就可以发现错误从而节省开发时间和成本)。换句话说如果你在DataFrame中调用的一个函数不是API的一部分编译器会捕获这个错误但是对于一个不存在的列名在编译期是检测不出来的

Spark中RDD、DataFrame和DataSet的区别 ?

由于DataSet都表示为lambda匿名函数和JVM类型对象所以编译时会检测到类型参数的任何不匹配另外在使用DataSet也可以在编译时检测到分析错误从而节省开发人员的时间和成本

2.结构化和半结构化数据的高级抽象和自定义视图

DataFrames作为一个行式数据集的集合可以将半结构化的数据以结构化的视图呈现出来例如您有一个海量的物联网设备数据集JSON表示由于JSON是一种半结构化的格式可以通过DataSet[DeviceIoTData]将强类型数据表达出来

JSON:{"device_id": 198164, "device_name": "sensor-pad-198164owomcJZ", "ip": "80.55.20.25", "cca2": "PL", "cca3": "POL", "cn": "Poland", "latitude": 53.080000, "longitude": 18.620000, "scale": "Celsius", "temp": 21, "humidity": 65, "battery_level": 8, "c02_level": 1408, "lcd": "red", "timestamp" :1458081226051}

可以通过Scala定义一个类-DeviceIoTData:

case class DeviceIoTData (battery_level: Long, c02_level: Long, cca2: String, cca3: String, cn: String, device_id: Long, device_name: String, humidity: Long, ip: String, latitude: Double, lcd: String, longitude: Double, scale:String, temp: Long, timestamp: Long)

这样我们就可以从JSON文件中读取数据了

// read the json file and create the dataset from the case class DeviceIoTData

// ds is now a collection of JVM Scala objects DeviceIoTData

val ds = spark.read.json(“/databricks-public-datasets/data/iot/iot_devices.json”).as[DeviceIoTData]

 

上述代码,经历了三段过程

1.Spark读取了JSON文件并根据定义的结构创建了一个DataFrame的数据集

2.在这个DataFrame的数据集Dataset[Row]实际是一个个的行对象因为它并不知道各自的类型

3.最后,sparkDataset[Row]转换为Dataset[DeviceIoTData],每一行数据被转化为了一个个的实例对象

3.API结构的易用性

虽然结构化会限制Spark对数据的操作但是DataSet引入了丰富的API来对高结构化的数据进行控制例如在进行agg, select, sum, avg, map, filter, 或者groupBy操作时,DataSetRDD更简单

// This operation results in another immutable Dataset. The query is simpler to //read,andexpressive

val dsAvgTmp = ds.filter(d => {d.temp > 25}).map(d => (d.temp, d.humidity, d.cca3)).groupBy($"_3").avg()

//display the resulting dataset

display(dsAvgTmp)

 

4.性能和优化

因为DataFrameDataSetAPI是建立在Spark SQL引擎之上的无论是java、scala还是python,所有涉及到关系型查询的语句都会经历相同的逻辑优化和执行计划不同的是, Dataset[T]类的API更适合数据工程任务,Dataset[Row](DataFrame)类的API则更适合交互式分析而且,spark作为一种编译器可以理解DataSet中的JVM对象可以通过Tungsten编码将这些对象进行快速的序列化和反序列化

Spark中RDD、DataFrame和DataSet的区别 ?


我们应该什么时候使用DataFrameDataSet

1.如果你想要丰富的语义高层次的抽象和特定情景的API,使用DataFrameDataSet。

2.如果你的处理要求涉及到filters, maps, aggregation, averages, sum, SQL queries, columnar access或其他lambda匿名函数使用DataFrameDataSet。

3.如果希望在编译时获得更高的类型安全性需要类型化的JVM对象利用Tungsten编码进行高效的序列化反序列化使用DataSet。

4.如果你想统一和简化sparkAPI,使用DataFrameDataSet。

5.如果你是一个R用户使用DataFrame。

6.如果你是一个Python用户使用DataFrame,如果你需要更多的控制功能尽量回到RDD。

 

注意:如果想从DataFrame或DataSet回到RDD,记得调用.rdd这个方法,如:

// select specific fields from the Dataset, apply a predicate using the where() method,

// convert to an RDD, and show first 10 RDD rows

val deviceEventsDS = ds.select($"device_name", $"cca3", $"c02_level").where($"c02_level" > 1300)

// convert to RDDs and take the first 10 rows

val eventsRDD = deviceEventsDS.rdd.take(10)

 

如何选择RDD还是DataFrame/DataSet?

前者提供低级别的功能和更多的控制后者允许自定义视图和结构提供高级和特定领域的操作节省空间并能够以极高的速度执行


参考资料:
1.https://www.zhihu.com/question/48684460
2.https://databricks.com/blog/2016/07/14/a-tale-of-three-apache-spark-apis-rdds-dataframes-and-datasets.html


以上.


听说,爱点赞的人运气都不会太差哦Spark中RDD、DataFrame和DataSet的区别 ?

如果有任何意见和建议,也欢迎在下方留言~





 

关注这个公众号,定期会有大数据学习的干货推送给你哦~


Spark中RDD、DataFrame和DataSet的区别 ?

点击这里查看往期精彩内容:

每日三问(0105)

每日三问(0106)

每日三问(0107)