我们正在运行以下阶段DAG,并且对于相对较小的shuffle数据大小(每个任务大约19MB)经历长时间的随机读取时间
一个有趣的方面是每个执行程序/服务器中的等待任务具有相同的随机读取时间。以下是它的含义示例:对于以下服务器,一组任务等待大约7.7分钟,另一组等待大约26秒。
这是同一阶段运行的另一个例子。该图显示了3个执行器/服务器,每个执行器/服务器具有统一的任务组,具有相等的随机读取时间由于投机执行,蓝色组代表被杀害的任务:
并非所有执行者都是这样的。有些可以在几秒钟内完成所有任务,并且这些任务的远程读取数据的大小与在其他服务器上等待很长时间的大小相同。 此外,这种类型的阶段在我们的应用程序运行时中运行2次。在每个阶段运行中,生成具有大的shuffle读取时间的这些任务组的服务器/执行器是不同的。
以下是其中一个服务器/主机的任务统计信息表的示例:
看起来负责此DAG的代码如下:
output.write.parquet("output.parquet")
comparison.write.parquet("comparison.parquet")
output.union(comparison).write.parquet("output_comparison.parquet")
val comparison = data.union(output).except(data.intersect(output)).cache()
comparison.filter(_.abc != "M").count()
我们非常感谢您对此的看法。
答案 0 :(得分:0)
显然问题是JVM垃圾收集(GC)。任务必须等到GC在远程执行程序上完成。等效的shuffle读取时间是由于几个任务在执行GC的单个远程主机上等待的事实。我们遵循了here发布的建议,问题减少了一个数量级。远程主机上的GC时间与本地随机播放读取时间之间仍然存在很小的相关性。在未来,我们会考虑尝试洗牌服务。
答案 1 :(得分:0)
因为谷歌把我带到这里遇到同样的问题,但我需要另一个解决方案......
小 shuffle 大小需要很长时间读取的另一个可能原因可能是数据被拆分到许多分区。例如(抱歉,这是 pyspark,因为它是我使用的全部):
my_df_with_many_partitions\ # say has 1000 partitions
.filter(very_specific_filter)\ # only very few rows pass
.groupby('blah')\
.count()
来自上面过滤器的shuffle write会非常小,所以对于后面的阶段我们将有非常少量的读取。但是要阅读它,您需要检查很多空分区。解决此问题的一种方法是:
my_df_with_many_partitions\
.filter(very_specific_filter)\
.repartition(1)\
.groupby('blah')\
.count()