J'ai RDD[Row]
, qui doit être conservé dans un référentiel tiers . Mais ce référentiel tiers accepte un maximum de 5 Mo par appel.
Je souhaite donc créer une partition basée sur la taille des données présentes dans RDD et non sur le nombre de lignes présentes dans RDD.
Comment trouver la taille d'une RDD
et créer des partitions à partir de celle-ci?
Comme Justin et Wang l'ont mentionné, il n'est pas simple d'obtenir la taille d'un RDD. Nous pouvons simplement faire une estimation.
Nous pouvons échantillonner un RDD puis utiliser SizeEstimator pour obtenir la taille de l’échantillon. Comme Wang et Justin l'ont mentionné, Sur la base des données de taille échantillonnées hors ligne, par exemple, X lignes utilisées par Y Go hors ligne, Z lignes au moment de l'exécution peuvent prendre Z * Y/X GB.
Voici l'exemple de code scala permettant d'obtenir la taille/l'estimation d'un RDD.
Je suis nouveau à Scala et étincelle. L'échantillon ci-dessous peut être écrit d'une meilleure façon
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
}
Une solution simple consiste à appeler les personnes suivantes, selon que vous souhaitiez stocker vos données sous forme sérialisée ou non, puis aller à la page "Stockage" de l'interface utilisateur. Vous devriez pouvoir déterminer la taille totale du RDD (mémoire + disque):
rdd.persist(StorageLevel.MEMORY_AND_DISK)
or
rdd.persist(StorageLevel.MEMORY_AND_DISK_SER)
Il n'est pas facile de calculer une taille de mémoire précise au moment de l'exécution. Vous pouvez toutefois essayer de faire une estimation au moment de l'exécution: sur la base des données de taille échantillonnées hors connexion, par exemple, X lignes utilisées Y hors ligne, Z lignes au moment de l'exécution peuvent prendre Z * Y/X GB; C'est semblable à Justin suggéré plus tôt.
J'espère que cela pourrait aider.
Je pense que RDD.count () vous donnera le nombre d'éléments dans le RDD
Cela dépendra de facteurs tels que la sérialisation, de sorte qu'il ne soit pas coupé et sec. Cependant, vous pouvez prendre un échantillon et procéder à des expérimentations sur ces données, en extrapolant à partir de là.
C’est la version à utiliser si vous travaillez réellement avec de grandes données sur un cluster - c’est-à-dire qu’elle élimine la collecte.
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)