Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 数据集相对于RDD的性能优势_Apache Spark_Rdd_Apache Spark Dataset - Fatal编程技术网

Apache spark 数据集相对于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的低内存管理=高级序列化。这意味着可序列化对象的堆外存储,在这种存储中,您只能读取对象的一

在阅读了几篇关于Spark的数据集的优秀文章(、和)之后,我将介绍next DataSet相对于RDD的性能优势:

  • 逻辑和物理计划优化
  • 严格打字
  • 矢量化操作
  • 低级别内存管理
  • 问题:

  • Spark的RDD还可以构建物理计划,并可以在同一阶段组合/优化多个转换。那么数据集相对于RDD有什么好处呢
  • 从中可以看到
    RDD[Person]
    的示例。数据集是否具有高级类型化
  • “矢量化操作”是什么意思
  • 据我所知,DataSet的低内存管理=高级序列化。这意味着可序列化对象的堆外存储,在这种存储中,您只能读取对象的一个字段,而无需反序列化。但是,当您只有
    内存中的
    持久性策略时,情况如何?在任何情况下,数据集都会序列化所有内容吗?与RDD相比,它会有任何性能优势吗
  • Spark的RDD还可以构建物理计划,并可以在同一阶段组合/优化多个转换。相比于RDD,数据集有什么好处

    当使用RDD时,您所写的就是您所得到的。虽然某些转换是通过链接优化的,但执行计划是DAG的直接转换。例如:

    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