如果要计数并稍后处理,是否需要缓存数据帧

时间:2018-11-01 16:10:03

标签: scala apache-spark apache-spark-sql

我有一个例子:

val df = ... // read from HDFS / file / ...
println(df.count)
val newDf = df.select // Other transformations... Keep processing the original df.

我的问题是,如果我正在处理过程中计数,我是否需要缓存原始数据帧?我的意思是,我计算df,然后继续对其进行转换和处理。
.count 是否意味着df将被计算两次?

1 个答案:

答案 0 :(得分:2)

在不了解您的用例和资源的情况下,很难给您一个确定的答案。但是,尽管Spark会两次访问源,但它很可能是负面的。

总体而言,有多个因素需要考虑:

  • 第一遍将加载多少数据。使用高效的磁盘输入格式Spark(例如Parquet),根本不需要完全加载数据集。这也适用于许多其他输入格式,包括但不限于JDBC阅读器。
  • 使用Dataset API缓存数据的成本非常高(这就是默认storage mode is MEMORY_AND_DISK的原因),并且很容易超过加载数据的成本。
  • 对后续处理有影响。通常,缓存会干扰分区修剪,谓词下推和预测(请参见Any performance issues forcing eager evaluation using count in spark?)。

所以...

  

.count是否意味着df将被计算两次?

在某种程度上取决于输入格式。纯文本格式(如JSON或CSV)比二进制源需要更多的重复工作。

  

我是否需要缓存原始数据帧

通常不会,除非您知道从存储中获取数据的成本证明了上面列出的缺点。

做出最终决定需要充分了解您的管道(主要是下游如何处理数据以及缓存如何影响数据流)和要优化的指标(延迟,总执行时间,运行所需资源的金钱成本)。 / p>

您还应该考虑替代count,例如处理InputMetrics或使用Accumulators