Apache spark 数据集相对于RDD的性能优势
在阅读了几篇关于Spark的数据集的优秀文章(、和)之后,我将介绍next DataSet相对于RDD的性能优势:Apache spark 数据集相对于RDD的性能优势,apache-spark,rdd,apache-spark-dataset,Apache Spark,Rdd,Apache Spark Dataset,在阅读了几篇关于Spark的数据集的优秀文章(、和)之后,我将介绍next DataSet相对于RDD的性能优势: 逻辑和物理计划优化 严格打字 矢量化操作 低级别内存管理 问题: Spark的RDD还可以构建物理计划,并可以在同一阶段组合/优化多个转换。那么数据集相对于RDD有什么好处呢 从中可以看到RDD[Person]的示例。数据集是否具有高级类型化 “矢量化操作”是什么意思 据我所知,DataSet的低内存管理=高级序列化。这意味着可序列化对象的堆外存储,在这种存储中,您只能读取对象的一
RDD[Person]
的示例。数据集是否具有高级类型化内存中的持久性策略时,情况如何?在任何情况下,数据集都会序列化所有内容吗?与RDD相比,它会有任何性能优势吗
rdd.mapPartitions(f).mapPartitions(g).mapPartitions(h).shuffle()
其中,shuffle
是一种任意洗牌转换(*byKey
,重新分区
,等等)。所有三个映射分区
(映射
,平面映射
,过滤器
)将链接起来,而不创建中间对象,但无法重新排列
与之相比,数据集
使用了更严格的编程模型,但可以使用多种技术优化执行,包括:
- 选择(
)下推。例如,如果您有:过滤器
可执行为:df.withColumn(“foo”,col(“bar”)+1)。其中(col(“bar”).isNotNull()
df.where(col(“bar”).isNotNull()).withColumn(“foo”,col(“bar”)+1)
- 早期预测(
)和消除。例如:选择
可以重写为:df.withColumn(“foo”,col(“bar”)+1)。选择(“foo”,“bar”)
避免获取和传递过时的数据。在极端情况下,它可以完全消除特定转换:df.选择(“foo”,“bar”)。带列(“foo”,列(“bar”)+1)
可以优化为df.withColumn(“foo”,col(“bar”)+1.选择(“bar”)
df.选择(“条”)
- 限制性数据模型,无需复杂和不可靠的静态代码分析即可进行依赖性分析李>
- 清晰的操作符语义。运算符没有副作用,我们清楚地区分确定性运算符和非确定性运算符
案例类人物(姓名:String,姓氏:String,年龄:Int)
val人员:RDD[人员]=???
我们想检索所有21岁以上的人的姓氏。使用RDD
可以表示为:
人
.map(p=>(p.姓氏,p.年龄))//f
.filter{case(u,age)=>age>21}//g
现在让我们问自己几个问题:
中的输入f
与age
变量age
之间的关系是什么g
然后f
是否与g
然后g
相同f
和f
是否没有副作用g
数据帧
版本相比:
people.toDF
.select(col(“姓氏”)、col(“年龄”)//f'
.where(col(“age”)>21)//g'
对于优化器和人类读者来说,答案都很清楚
当使用静态类型的数据集时,这会产生一些进一步的后果
数据集有更高级的类型化吗
- 否-如果您关心优化的话。最高级的优化仅限于
Dataset[Row]
,目前无法对复杂类型层次结构进行编码
- 也许-如果您接受Kryo或Java编码器的开销
“矢量化操作”是什么意思
在优化环境中,我们通常指循环矢量化/循环展开。Spark SQL使用代码生成创建编译器友好的高级转换版本,可以进一步优化以利用矢量化指令集
据我所知,DataSet的低内存管理=高级序列化
不完全是。使用本机分配的最大优点是转义垃圾收集器循环。由于垃圾收集通常是Spark中的一个限制因素,这是一个巨大的改进,特别是在需要大型数据结构(如准备洗牌)的环境中
另一个重要方面是柱状存储,它可以实现有效压缩(可能会降低内存占用)并优化对压缩数据的操作
通常您可以在普通的rdd
上使用手工编写的代码应用完全相同类型的优化。毕竟数据集
由RDD
支持。区别只是需要付出多少努力
- 手工编制的执行计划优化相对容易实现
- 使代码编译器友好需要一些更深入的知识,并且容易出错和冗长
- 使用本机内存alloca的
sun.misc.Unsafe