【问题标题】:Why persist () are lazily evaluated in Spark为什么persist()在Spark中被懒惰地评估
【发布时间】:2015-12-24 21:48:40
【问题描述】:

我理解在 Scala 中有两种类型的操作

  1. 转换
  2. 操作

像 map()、filter() 这样的转换是惰性求值的。因此,可以在 Action 执行时进行优化。例如,如果我执行 action first() 那么 Spark 将优化为只读第一行。

但是为什么persist() 操作被延迟评估。因为无论我采用哪种方式,无论是热切地还是懒惰地,它都会按照存储级别持久化整个 RDD。

您能否详细说明为什么persist() 是转换而不是操作。

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    对于初学者来说,渴望持久性会污染整个管道。 cachepersist 仅表示意图。这并不意味着我们将永远到达 RDD 被物化并且可以实际缓存的地步。此外,在某些情况下会自动缓存数据。

    因为无论我采用哪种方式,无论是急切还是懒惰,它都会按照存储级别保留整个 RDD。

    这并不完全正确。事情是,persist 不是持久的。正如 in the documentation 明确指出的 MEMORY_ONLY 持久性级别:

    如果 RDD 不适合内存,则某些分区将不会被缓存,并且会在每次需要时重新计算。

    使用MEMORY_AND_DISK,剩余数据存储到磁盘,但如果没有足够的内存用于后续缓存,仍然可以将其逐出。更重要的是:

    Spark 自动监控每个节点上的缓存使用情况,并以最近最少使用 (LRU) 的方式丢弃旧数据分区。

    您还可以争辩说,cache / persist 在语义上与针对特定 IO 副作用执行的 Spark 操作不同。 cache 更多的是对 Spark 引擎的提示,我们可能希望稍后重用这段代码。

    【讨论】:

      【解决方案2】:

      如果你有一些你可能会或可能不会使用的数据,那么让persist() 急切会是低效的。正常的 Spark 转换对应于 Scala 中的 def。持久化将其变成lazy val

      【讨论】:

        【解决方案3】:

        persist 是一个令人困惑的名称,因为它不会在您的上下文生命周期之外持续存在。

        persist 与缓存相同。数据在第一次计算时被缓存,因此如果您在另一个计算中使用您的 RDD,则不会重新计算结果。

        【讨论】:

        • False 它们不一样,persist 保存在磁盘上,但cache 保存在内存中,此外,persist 有多种处理scalajava API 的方法。
        • 我支持(部分更正):cache() = persist() = persist(StorageLevel.MEMORY_ONLY) 它仍然是一种临时缓存中间计算的方法。它只在需要时完成,因此它是一个惰性操作
        • 这是我的问题“为什么要让 persist() 调用变得懒惰?”因为最终它将根据存储级别(如 MEMORY_ONLY、DISK_ONLY 等)存储(针对该上下文生存期)RDD。在其他转换中,我同意我们可以通过惰性实现成本优化。
        • 我不知道是否有强调的优势,因为你大概会使用 RDD 但也没有理由不等待
        猜你喜欢
        • 2015-09-06
        • 2017-01-13
        • 2016-05-12
        • 2014-10-10
        • 1970-01-01
        • 1970-01-01
        • 2017-04-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多