如何找到RDD的大小

时间:2015-07-14 04:39:44

标签: apache-spark apache-spark-sql

我有RDD[Row],需要持久保存到第三方存储库。 但是这个第三方存储库在一次通话中最多可接受5 MB。

所以我想根据RDD中存在的数据大小创建分区,而不是基于RDD中存在的行数。

如何找到RDD的大小并根据它创建分区?

5 个答案:

答案 0 :(得分:11)

正如Justin和Wang所说,获得RDD的大小并不是直截了当的。我们可以做一个估计。

我们可以对RDD进行采样,然后使用SizeEstimator来获取样本的大小。 正如王和贾斯汀所说, 基于离线采样的大小数据,比如X行使用Y GB离线,Z行在运行时可以采用Z * Y / X GB

以下是获取RDD大小/估计值的示例scala代码。

我是scala和spark的新手。下面的示例可能会以更好的方式编写

def getTotalSize(rdd: RDD[Row]): Long = {
  // This can be a parameter
  val NO_OF_SAMPLE_ROWS = 10l;
  val totalRows = rdd.count();
  var totalSize = 0l
  if (totalRows > NO_OF_SAMPLE_ROWS) {
    val sampleRDD = rdd.sample(true, NO_OF_SAMPLE_ROWS)
    val sampleRDDSize = getRDDSize(sampleRDD)
    totalSize = sampleRDDSize.*(totalRows)./(NO_OF_SAMPLE_ROWS)
  } else {
    // As the RDD is smaller than sample rows count, we can just calculate the total RDD size
    totalSize = getRDDSize(rdd)
  }

  totalSize
}

def getRDDSize(rdd: RDD[Row]) : Long = {
    var rddSize = 0l
    val rows = rdd.collect()
    for (i <- 0 until rows.length) {
       rddSize += SizeEstimator.estimate(rows.apply(i).toSeq.map { value => value.asInstanceOf[AnyRef] })
    }

    rddSize
}

答案 1 :(得分:6)

一种直接的方式是调用以下,取决于您是否要以序列化形式存储数据,然后转到spark UI“存储”页面,您应该能够计算出RDD的总大小(内存+磁盘):

rdd.persist(StorageLevel.MEMORY_AND_DISK)

or

rdd.persist(StorageLevel.MEMORY_AND_DISK_SER)

在运行时计算准确的内存大小并不容易。您可以尝试在运行时进行估算:基于离线采样的大小数据,例如,X行使用Y GB离线,Z行在运行时可以采用Z * Y / X GB;这与贾斯汀早些时候提出的相似。

希望这可以提供帮助。

答案 2 :(得分:4)

我认为RDD.count()会为您提供RDD中元素的数量

答案 3 :(得分:3)

这取决于序列化等因素,因此不会切割干燥。但是,您可以采集样本集并对该样本数据进行一些实验,从那里进行推断。

答案 4 :(得分:0)

如果您实际上是在集群上使用大数据,则使用此版本-即,它消除了收集。

def calcRDDSize(rdd: RDD[Row]): Long = {
  rdd.map(_.mkString(",").getBytes("UTF-8").length.toLong)
     .reduce(_+_) //add the sizes together
}

def estimateRDDSize( rdd: RDD[Row], fraction: Double ) : Long = {
  val sampleRDD = rdd.sample(true,fraction)
  val sampleRDDsize = calcRDDSize(sampleRDD)
  println(s"sampleRDDsize is ${sampleRDDsize/(1024*1024)} MB")

  val sampleAvgRowSize = sampleRDDsize / sampleRDD.count()
  println(s"sampleAvgRowSize is $sampleAvgRowSize")

  val totalRows = rdd.count()
  println(s"totalRows is $totalRows")

  val estimatedTotalSize = totalRows * sampleAvgRowSize
  val formatter = java.text.NumberFormat.getIntegerInstance
  val estimateInMB = formatter.format(estimatedTotalSize/(1024*1024))
  println(s"estimatedTotalSize is ${estimateInMB} MB")

  return estimatedTotalSize
}

// estimate using 15% of data
val size = estimateRDDSize(df.rdd,0.15)