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

时间:2017-05-13 06:29:36

标签: scala performance 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]

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

enter image description here

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

enter image description here

所以,我的怀疑是:

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

1 个答案:

答案 0 :(得分:8)

  

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

这两项计数实际上都是两步操作。不同之处在于,ds.count的情况下,最终聚合由其中一个执行者执行,而ds.rdd.count aggregates the final result on the driver则执行,因此此步骤不会反映在DAG中:

  

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

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

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

相关:How to know which count query is the fastest?