对于在第一个Action之前重用的数据帧,是否需要缓存?

时间:2019-06-05 08:54:34

标签: apache-spark apache-spark-sql

我有一个数据框,在将结果加入最终DF之前,我以不同的方式独立对其进行了转换。 中间转换的数据帧永远不会在任何“动作”中使用。 只有将所有部分连接在一起后,才可以调用第一个动作。 我的问题是-那么我应该缓存第一个数据帧吗? 示例:

arpu_df=get_arpu_df(..). #.cache() will help here?
sample_by_arpu_ranges=arpu_df.filter("arpu>50").sample(False,0.4)\
    .union(
        arpu_df.filter("arpu>20 and arpu<=50").sample(False,0.1)
        )\
    .union(
        arpu_df.filter("arpu<=20").sample(False,0.02)
        ).select("base_subsc_id")
sample_by_arpu_ranges.count()
据我所知,

sample是转型。 我想知道是否arpu_df部分将被重新计算以应用每个过滤器,还是逻辑计划构建器会理解它可以在计划的不同部分中重用它?

2 个答案:

答案 0 :(得分:1)

仅在调用操作后才会触发缓存,因此对于您而言,答案是cache在调用sample_by_arpu_ranges.count()之前将无益。常见的解决方法是在count()之后调用费用较低的操作cache(),然后您的代码将成为下一个代码:

arpu_df=get_arpu_df(..)

arpu_df.cache()
arpu_df.count()

sample_by_arpu_ranges=arpu_df.filter("arpu>50").sample(False,0.4)\
    .union(
        arpu_df.filter("arpu>20 and arpu<=50").sample(False,0.1)
        )\
    .union(
        arpu_df.filter("arpu<=20").sample(False,0.02)
        ).select("base_subsc_id")
sample_by_arpu_ranges.count()

答案 1 :(得分:0)

答案在您的问题内。您只有一个动作,因此所有转换都将在那个时候完成。在这种情况下,您不需要持久化(或缓存)数据框。

仅当您需要再次计算转换时,持久化才有用

示例:

arpu_df=get_arpu_df(..)
sample_by_arpu_ranges=arpu_df.filter("arpu>50").sample(False,0.4)\
    .union(
        arpu_df.filter("arpu>20 and arpu<=50").sample(False,0.1)
        )\
    .union(
        arpu_df.filter("arpu<=20").sample(False,0.02)
        ).select("base_subsc_id").persist() //here you persist sample_by_arpu_ranges because you know you will have multiple actions on it

sample_by_arpu_ranges.count() // 1st action

sample_by_arpu_ranges.write.parquet("path") // 2nd action  

在该示例中,sample_by_arpu_ranges将在第一个动作期间保持不变,因此对于第二个动作,sample_by_arpu_ranges将准备就绪。

->不能一with而就:

arpu_df = spark.read.parquet(path) 
sample_by_arpu_ranges=arpu_df.filter(...)
sample_by_arpu_ranges.count()

发生了什么:

  • sample_by_arpu_ranges.count()
  • arpu_df = spark.read.parquet(path)
  • sample_by_arpu_ranges = arpu_df.filter(...)
  • 计数

->不保留arpu_df或sample_by_arpu_ranges,但您不再需要

->不能持续执行多个操作:

arpu_df = spark.read.parquet(path) 
sample_by_arpu_ranges=arpu_df.filter(...)
arpu_df.count()
sample_by_arpu_ranges.count()

发生了什么:

  • arpu_df.count()
  • arpu_df = spark.read.parquet(path)
  • 计数

->不保留arpu_df!

  • sample_by_arpu_ranges.count()

  • arpu_df = spark.read.parquet(path)//您必须再次阅读!

  • sample_by_arpu_ranges = arpu_df.filter(...)

  • 计数

->持续执行多个操作:

arpu_df = spark.read.parquet(path).persist
sample_by_arpu_ranges=arpu_df.filter(...)
arpu_df.count()
sample_by_arpu_ranges.count()

发生了什么:

  • arpu_df.count()
  • arpu_df = spark.read.parquet(path)
  • 持久--->将arpu_df保存在缓存中
  • 计数
  • sample_by_arpu_ranges.count()
  • sample_by_arpu_ranges = arpu_df(从缓存中获取,无需读取 它).filter(...)
  • 计数