两个非常相似的 Spark Dataframes 之间性能差异的可能原因

Possible causes of performance difference between two very similar Spark Dataframes

我正在努力为我正在制作原型的推荐引擎改进某些 Spark 操作的性能。我偶然发现我正在使用的数据帧之间存在显着的性能差异。在 describe() 的结果下方。

df1(快速,numPartitions = 4):

+-------+------------------+--------------------+
|summary|           item_id|          popularity|
+-------+------------------+--------------------+
|  count|            187824|              187824|
|   mean| 96693.34836868558|                 1.0|
| stddev|55558.023793621316|5.281958866780519...|
|    min|                 0|  0.9999999999999998|
|    max|            192806|                 1.0|
+-------+------------------+--------------------+

df2(大约慢 10 倍,numPartitions = ±170):

+-------+-----------------+-----------------+
|summary|          item_id|            count|
+-------+-----------------+-----------------+
|  count|           187824|           187824|
|   mean|96693.34836868558|28.70869537439305|
| stddev|55558.02379362146|21.21976457710462|
|    min|                0|                1|
|    max|           192806|              482|
+-------+-----------------+-----------------+

两个 DataFrame 都被缓存,在行 (187824) 和列 (2) 方面大小相同,并且具有相同的 item_id 列。主要区别在于第 1 帧在第二列中包含浮点数,而第 2 帧包含整数。

似乎 DataFrame 2 的每个操作都慢得多,从简单的 .describe().show() 操作到更复杂的 .subtract().subtract().take()。在后一种情况下,DataFrame 2 需要 18 秒,而第一帧需要 2 秒(慢了将近 10 倍!)。

我不知道从哪里开始寻找造成这种差异的原因的解释。非常感谢任何正确方向的提示或推动。

更新:正如 Viacheslav Rodionov 所提议的,数据帧的分区数量似乎是 df2 性能问题的原因。

深入挖掘,两个数据帧都是对同一个原始数据帧进行 .groupBy().agg().sortBy() 操作的结果。 .groupBy().agg() 操作产生 200 个分区,然后 .sortBy() returns 分别产生 4 和 ±170 个分区,为什么会这样?

我先看看 df.rdd.getNumPartitions()

较少数量的较大分区几乎总是一个好主意,因为它允许更好地压缩数据并执行更多实际工作而不是操作文件。

要查看的另一件事是数据的外观。它适合您尝试执行的任务吗?

  • 如果它按您用来应用 BETWEEN 操作的日期字段排序,它将比仅处理未排序的数据更快。
  • 如果您使用特定的月份或年份,则按它们对数据进行分区是有意义的。
  • ID 也是如此。如果您使用某些 ID,请通过 partitioning/sorting 您的数据集将相同的 ID 'closer' 彼此放在一起。

我在存储数据时的经验法则 - 首先按几个低基数字段(主要是布尔值和日期)进行分区,然后使用 所有 对其他字段进行排序 sortWithinPartitions按数据重要性排序。这样您将获得最佳压缩率(意味着更快的处理时间)和更好的数据局部性(同样更快的处理时间)。但一如既往,这一切都取决于您的用例,请始终考虑您如何处理数据并相应地进行准备。