Spark:解决性能密集型命令,如collect(),groupByKey(),reduceByKey()

Rav*_*abu 2 performance scala apache-spark rdd

我知道一些Spark Actions collect()会导致性能问题.

它已在文档中引用

要打印驱动程序上的所有元素,可以使用collect()方法首先将RDD带到驱动程序节点:rdd.collect().foreach(println).但是,这可能会导致驱动程序内存不足,

因为collect()将整个RDD提取到一台机器上 ; 如果您只需要打印RDD的一些元素,更安全的方法是使用take():rdd.take(100).foreach(println).

还有一个相关的SE问题:当按键分组时,Spark会耗尽内存

我已经知道,groupByKey(), reduceByKey()如果没有正确设置并行性,可能会导致内存不足.

我没有得到关于其他转换和动作命令的足够证据,这些命令必须谨慎使用.

这三个是唯一要解决的命令?我对下面的命令也有疑问

  1. aggregateByKey()
  2. sortByKey()
  3. persist()/cache()

如果您提供有关密集命令(全局跨分区而不是单个分区或低性能命令)的信息,那将是很好的,这些命令必须通过更好的防护来解决.

zer*_*323 6

您必须考虑三种类型的操作:

  • 变换仅使用实施mapPartitions(WithIndex)filter,map,flatMap等.通常这将是最安全的组.可能遇到的最大可能问题是广泛溢出磁盘.
  • 需要改组的转换.它包括明显嫌疑人等的不同变体combineByKey(groupByKey,reduceByKey,aggregateByKey)或join和较不明显的像sortBy,distinctrepartition.如果没有上下文(数据分布,精确的还原功能,分区器,资源),很难判断特定的转换是否有问题.有两个主要因素:
    • 网络流量和磁盘IO - 任何未在内存中执行的操作将至少慢一个数量级.
    • 偏斜的数据分布 - 如果分布高度倾斜,则随机播放可能会失败,或者后续操作可能会受到次优资源分配的影响
  • 需要将数据传入和传出驱动程序的操作.通常,它涵盖了类似于collecttake从本地one(parallelize)创建分布式数据结构的操作.

    此类别的其他成员broadcasts(包括自动广播联接)和accumulators.总成本当然取决于特定操作和数据量.

虽然其中一些操作可能很昂贵,但是没有一个特别糟糕(包括妖魔化groupByKey)本身.显然,最好避免网络流量或额外的磁盘IO,但实际上,在任何复杂的应用程序中都无法避免它.

关于缓存你可能会发现Spark:为什么我必须明确告诉缓存什么?有用.