繁体   English   中英

在Apache Spark中,如何使RDD / DataFrame操作变得懒惰?

[英]In Apache Spark, how to make an RDD/DataFrame operation lazy?

假设我想编写一个可转换DataFrame的函数foo:

object Foo {
def foo(source: DataFrame): DataFrame = {
...complex iterative algorithm with a stopping condition...
}
}

由于foo的实现具有许多“动作”(收集,减少等),因此调用foo将立即触发昂贵的执行。

这不是什么大问题,但是由于foo仅将一个DataFrame转换为另一个,因此按照惯例,最好允许延迟执行:仅在将结果DataFrame或其派生对象用于foo时才应执行foo的实现。驱动程序(通过另一个“操作”)。

到目前为止,可靠地实现此目标的唯一方法是将所有实现写入SparkPlan,然后将其叠加到DataFrame的SparkExecution中,这非常容易出错,并且涉及许多样板代码。 推荐的方法是什么?

对我来说,要实现的目标还不是很清楚,但是Scala本身至少提供了一些可能有用的工具:

  • 惰性值:

     val rdd = sc.range(0, 10000) lazy val count = rdd.count // Nothing is executed here // count: Long = <lazy> count // count is evaluated only when it is actually used // Long = 10000 
  • 按名称调用(在函数定义中用=>表示):

     def foo(first: => Long, second: => Long, takeFirst: Boolean): Long = if (takeFirst) first else second val rdd1 = sc.range(0, 10000) val rdd2 = sc.range(0, 10000) foo( { println("first"); rdd1.count }, { println("second"); rdd2.count }, true // Only first will be evaluated ) // first // Long = 10000 

    注意 :实际上,您应该创建本地延迟绑定,以确保不会在每次访问时都对参数进行求值。

  • Stream这样的无限懒惰集合

     import org.apache.spark.mllib.random.RandomRDDs._ val initial = normalRDD(sc, 1000000L, 10) // Infinite stream of RDDs and actions and nothing blows :) val stream: Stream[RDD[Double]] = Stream(initial).append( stream.map { case rdd if !rdd.isEmpty => val mu = rdd.mean rdd.filter(_ > mu) case _ => sc.emptyRDD[Double] } ) 

其中一些子集应该足以实现复杂的惰性计算。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM