两个非常相似的 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
按数据重要性排序。这样您将获得最佳压缩率(意味着更快的处理时间)和更好的数据局部性(同样更快的处理时间)。但一如既往,这一切都取决于您的用例,请始终考虑您如何处理数据并相应地进行准备。
我正在努力为我正在制作原型的推荐引擎改进某些 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
按数据重要性排序。这样您将获得最佳压缩率(意味着更快的处理时间)和更好的数据局部性(同样更快的处理时间)。但一如既往,这一切都取决于您的用例,请始终考虑您如何处理数据并相应地进行准备。