Apache spark 如何找到RDD的大小

Apache spark 如何找到RDD的大小,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,我有RDD[Row],需要将其保存到第三方存储库中。 但该第三方存储库在一次调用中最多可接受5MB 所以我想根据RDD中存在的数据的大小而不是RDD中存在的行数来创建分区 如何找到RDD的大小并基于它创建分区?这将取决于序列化等因素,因此它不是一成不变的。但是,您可以获取一个样本集,并对该样本数据进行一些实验,从中进行推断。一个简单的方法是调用以下命令,这取决于您是否希望以序列化形式存储数据,然后转到spark UI“存储”页面,您应该能够计算出RDD的总大小(内存+磁盘): 在运行时计算准确的

我有
RDD[Row]
,需要将其保存到第三方存储库中。 但该第三方存储库在一次调用中最多可接受5MB

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


如何找到
RDD的大小并基于它创建分区?

这将取决于序列化等因素,因此它不是一成不变的。但是,您可以获取一个样本集,并对该样本数据进行一些实验,从中进行推断。

一个简单的方法是调用以下命令,这取决于您是否希望以序列化形式存储数据,然后转到spark UI“存储”页面,您应该能够计算出RDD的总大小(内存+磁盘):

在运行时计算准确的内存大小并不容易。不过,您可以尝试在运行时进行估计:基于脱机采样的大小数据,例如,脱机使用的X行为Y GB,运行时的Z行可能需要Z*Y/X GB;这与Justin之前建议的类似


希望这能有所帮助。

正如Justin和Wang提到的,要得到RDD的大小并不是一个简单的问题。我们可以做一个估计

我们可以对RDD进行采样,然后使用来获得样本的大小。 正如王和贾斯汀提到的, 基于脱机采样的大小数据,例如,X行脱机使用Y GB,运行时Z行可能会使用Z*Y/X GB

下面是示例scala代码,用于获取RDD的大小/估计值

我是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
}
def gettotalize(rdd:rdd[Row]):Long={
//这可以是一个参数
样本行的val编号=10l;
val totalRows=rdd.count();
var totalSize=0升
if(总计行>无样本行){
val sampleRDD=rdd.sample(真,没有样本行)
val sampleRDDSize=getRDDSize(sampleRDD)
totalSize=sampleRDDSize.*(totalRows)。/(没有样本行)
}否则{
//由于RDD小于样本行数,我们可以只计算RDD的总大小
totalSize=getRDDSize(rdd)
}
总尺寸
}
def getRDDSize(rdd:rdd[行]):长={
变量rddSize=0l
val rows=rdd.collect()
for(i值.asInstanceOf[AnyRef]})
}
rddSize
}

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

如果您实际使用集群上的大数据,则可以使用此版本,即它消除了收集

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)

考虑到我有一个带字符串的RDD。是否需要遍历所有RDD并使用String?siz()获取大小?@sag这是一种方法,但会增加执行时间。如果rdd不是非常大,您可以这样做。谢谢您的回答。是的,这将有助于找到大小。但我想在管道/代码执行过程中检查这一点。所以手动检查Spark UI对我来说不是一个选项。我认为这不容易计算在运行时读取准确的内存大小。不过,您可以尝试在运行时进行估计:基于脱机采样的大小数据,例如,X行脱机使用Y GB,Z行在运行时可能会占用Z*Y/X GB;这与Justin先前建议的类似。随机问题,当我执行rdd.cache()时我在UI中看不到它。仅内存存储未显示?如何获取RDD大小?我正在运行作业,并以GB为单位估计RDD大小,但我无法在Spark代码中访问此信息。我找到了该值。asInstanceOf[AnyRef]在估计值方面,toString比toString更有效。如果值为null,toString可以抛出null指针,而且似乎强制转换不会有此问题,因此它也更安全。@SamuelAlexander
rdd.sample(true,没有样本行)
将返回完整的RDD,第二个参数应为介于0和之间的数字1@TheProletariat-是的,你也可以用你的代码编辑答案。这个例子是错误的。正如@VictorP.指出的,没有任何一行必须是分馏Hello@Yiying,欢迎来到StackOverflow。海报要求的是RDD的大小,而不仅仅是数字行。也许你可以扩展你的答案,这样海报就不需要任何进一步的澄清。一旦你有了足够的声誉,你可以留下评论,如果你愿意的话。这个问题要求以信息单位(字节)为单位的大小但是,
count
也是一个衡量大小的指标——这个答案并不能真正回答这个问题,但确实为理想答案添加了信息。我认为可能有一个解决方案可以避免sag对上面的答案使用
collect
(您在这个解决方案中就是这么做的),但仍然使用spark的
SizeEstimator。估计
,这可能比在行上运行
mkString
并查看字符串长度更准确。估计只有将其存储为字符串时,此答案才会起作用,这取决于RDD的持久化方式(序列化为字符串、序列化为Java对象等)
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)