Spark:如何获取写入的行数?

时间:2016-05-28 07:56:24

标签: apache-spark

我想知道是否有办法知道Spark保存操作写入的行数。我知道在编写之前对RDD进行计数就足够了,但是我想知道是否有办法在没有这样做的情况下获得相同的信息。

谢谢你, 马可

3 个答案:

答案 0 :(得分:8)

如果您真的想要,可以添加自定义侦听器并从outputMetrics中提取已写入的行数。非常简单的示例可能如下所示:

import org.apache.spark.scheduler.{SparkListener, SparkListenerTaskEnd}

var recordsWrittenCount = 0L

sc.addSparkListener(new SparkListener() { 
  override def onTaskEnd(taskEnd: SparkListenerTaskEnd) {
    synchronized {
      recordsWrittenCount += taskEnd.taskMetrics.outputMetrics.recordsWritten 
    }
  }
})

sc.parallelize(1 to 10, 2).saveAsTextFile("/tmp/foobar")
recordsWrittenCount
// Long = 10

但这部分API仅供内部使用。

答案 1 :(得分:7)

接受的答案更符合OP的具体需求(如各种评论所述),但这个答案适合大多数人。

最有效的方法是使用累加器:http://spark.apache.org/docs/latest/programming-guide.html#accumulators

val accum = sc.accumulator(0L)

data.map { x =>
  accum += 1
  x
}
.saveAsTextFile(path)

val count = accum.value

然后你可以将它包装在一个有用的皮条客中:

implicit class PimpedStringRDD(rdd: RDD[String]) {
  def saveAsTextFileAndCount(p: String): Long = {
    val accum = rdd.sparkContext.accumulator(0L)

    rdd.map { x =>
      accum += 1
      x
    }
    .saveAsTextFile(p)

    accum.value
  }
}

所以你可以做到

val count = data.saveAsTextFileAndCount(path)

答案 2 :(得分:0)

如果你看一下

]

您会看到它与taskEnd.taskInfo.accumulables 中的AccumulableInfo按顺序捆绑在一起。

ListBuffer

您可以清楚地看到输出行的数量位于listBuffer的第7个位置,因此获取正在写入的行的正确方法是

AccumulableInfo(1,Some(internal.metrics.executorDeserializeTime),Some(33),Some(33),true,true,None), 
AccumulableInfo(2,Some(internal.metrics.executorDeserializeCpuTime),Some(32067956),Some(32067956),true,true,None), AccumulableInfo(3,Some(internal.metrics.executorRunTime),Some(325),Some(325),true,true,None), 
AccumulableInfo(4,Some(internal.metrics.executorCpuTime),Some(320581946),Some(320581946),true,true,None), 
AccumulableInfo(5,Some(internal.metrics.resultSize),Some(1459),Some(1459),true,true,None), 
AccumulableInfo(7,Some(internal.metrics.resultSerializationTime),Some(1),Some(1),true,true,None), 
AccumulableInfo(0,Some(number of output rows),Some(3),Some(3),true,true,Some(sql)

我们可以通过以下方式获取行(我刚刚修改了@ zero323的答案)

taskEnd.taskInfo.accumulables(6).value.get