我有一个spark应用程序,我需要从执行程序获取数据到驱动程序,我正在使用collect()
。但是,我也遇到了toLocalIterator()
。据我所知,在互联网上有toLocalIterator()
,它会返回一个迭代器,而不是立即发送整个RDD,因此它具有更好的内存性能,但速度呢?在执行/计算时间方面,collect()
和toLocalIterator()
之间的性能如何?
答案 0 :(得分:2)
此问题的答案取决于您在制作df.collect()和df.rdd.toLocalIterator()之后会做什么。例如,如果您要处理一个大约700万行的相当大的文件,并且对于其中的每个记录,则在完成所有必需的转换之后,您需要遍历数据帧中的每个记录,并分批进行服务调用100 对于df.collect(),它将把整个记录集转储到驱动程序,因此驱动程序将需要大量的内存。与toLocalIterator()一样,它仅在总记录的分区上返回迭代器,因此驱动程序不需要大量的内存。因此,如果要在同一个群集内的并行工作流中加载如此大的文件,则df.collect()会给您带来很多开销,而toLocalIterator()则不会,而且也会更快,更可靠。 >
另一方面,如果您打算在df.collect()或df.rdd.toLocalIterator()之后进行一些转换,那么df.collect()会更快。
如果您的文件太小,以至于Spark的默认分区逻辑根本无法将其分解为多个分区,则df.collect()会更快。
答案 1 :(得分:1)
这导致多个Spark作业,如果输入RDD是广泛转换的结果(例如,使用不同的分区器连接),为了避免重新计算输入,RDD应首先被缓存。
这意味着在最糟糕的情况下(根本没有缓存),n分区的时间可能比collect
贵。即使数据为cached
,启动多个Spark作业的开销在大型数据集上也会很重要。但是,较低的内存占用可以部分地弥补这一点,加深特定配置。
总体而言,这两种方法都是低效的,应该避免在大型数据集上使用。
答案 2 :(得分:0)
对于toLocalIterator,它用于将分散在集群周围的RDD中的数据收集到一个唯一的节点,即运行该程序的节点,并对同一节点中的所有数据执行某些操作。它类似于collect方法,但它不会返回List,而是返回Iterator。
因此,在使用foreach将函数应用于RDD之后,您可以调用toLocalIterator来获取RDD的所有内容的迭代器并对其进行处理。但是,请记住,如果您的RDD非常大,您可能会遇到内存问题。如果要在执行所需的操作后再次将其转换为RDD,请使用SparkContext对其进行并行化。