首页 > 解决方案 > 如果要计数并稍后处理它,是否需要缓存数据帧

问题描述

我有一个例子:

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

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

标签: scalaapache-sparkapache-spark-sql

解决方案


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

总的来说,有多个因素需要考虑:

  • 第一次将加载多少数据。借助高效的磁盘输入格式 Spark(如 Parquet),Spark 根本不需要完全加载数据集。这也适用于许多其他输入格式,包括但不限于 JDBC 阅读器。
  • 使用 API 缓存数据的成本Dataset相当高(这就是为什么默认存储模式是MEMORY_AND_DISK)并且很容易超过加载数据的成本。
  • 对后续加工的影响。一般来说,缓存会干扰分区修剪、谓词下推和预测(请参阅任何性能问题强制使用 spark 中的计数进行急切评估?)。

所以...

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

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

我需要缓存原始数据帧吗

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

做出最终决定需要充分了解您的管道(主要是如何在下游处理数据以及缓存如何影响这一点)和您想要优化的指标(延迟、总执行时间、运行所需资源的货币成本)。

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


推荐阅读