为什么dataset.count()比rdd.count()更快?

him*_*ian 5 performance scala apache-spark apache-spark-sql apache-spark-dataset

我创建了一个Spark Dataset[Long]:

scala> val ds = spark.range(100000000)
ds: org.apache.spark.sql.Dataset[Long] = [id: bigint]
Run Code Online (Sandbox Code Playgroud)

当我运行ds.count它给我结果0.2s(在4 Core 8GB机器上).此外,它创建的DAG如下:

在此输入图像描述

但是,当我跑的ds.rdd.count时候给了我结果4s(同一台机器).但它创建的DAG如下:

在此输入图像描述

所以,我的怀疑是:

  1. 为什么ds.rdd.count只创造一个阶段而ds.count创造两个阶段?
  2. 此外,当ds.rdd.count只有一个阶段时,为什么它比ds.count两个阶段慢?

use*_*411 9

为什么ds.rdd.count只创建一个阶段而ds.count创建了两个阶段?

这两项计数实际上都是两步操作.不同之处在于,如果ds.count最终聚合由其中一个执行程序执行,同时ds.rdd.count在驱动程序上聚合最终结果,则此步骤不会反映在DAG中:

此外,当ds.rdd.count只有一个阶段时,为什么它更慢

同上.此外ds.rdd.count,必须初始化(以及后来的垃圾收集)1亿个Row对象,这几乎是免费的,并且可能占据了这里的大部分时间差异.

最后range类似的对象不是一个很好的基准测试工具,除非非常谨慎使用.根据上下文计算,超出范围可以表示为恒定时间操作,即使没有明确的优化也可以非常快(例如参见spark.sparkContext.range(0, 100000000).count),但不能反映实际工作负载的性能.

相关:如何知道哪个计数查询最快?

  • 相关问题:我的理解是否正确,rdd.count 将运行分布式作业,但是 ds.count 会将所有数据带给驱动程序?回答我自己的问题:这不是真的:) (2认同)