Il y a un certain nombre de questions sur la façon d'obtenir le nombre de partitions d'un n RDD
et ou d'un DataFrame
: les réponses sont invariablement:
rdd.getNumPartitions
ou
df.rdd.getNumPartitions
Malheureusement, c'est une opération chère sur un DataFrame
car le
df.rdd
nécessite la conversion de DataFrame
en rdd
. C'est dans l'ordre du temps qu'il faut pour exécuter
df.count
J'écris une logique qui facultativementrepartition
ou coalesce
est un DataFrame
- selon que le actuel nombre de partitions se situaient dans une plage de valeurs acceptables ou au-dessous ou au-dessus.
def repartition(inDf: DataFrame, minPartitions: Option[Int],
maxPartitions: Option[Int]): DataFrame = {
val inputPartitions= inDf.rdd.getNumPartitions // EXPENSIVE!
val outDf = minPartitions.flatMap{ minp =>
if (inputPartitions < minp) {
info(s"Repartition the input from $inputPartitions to $minp partitions..")
Option(inDf.repartition(minp))
} else {
None
}
}.getOrElse( maxPartitions.map{ maxp =>
if (inputPartitions > maxp) {
info(s"Coalesce the input from $inputPartitions to $maxp partitions..")
inDf.coalesce(maxp)
} else inDf
}.getOrElse(inDf))
outDf
}
Mais nous ne pouvons pas nous permettre de supporter le coût du rdd.getNumPartitions
for everyDataFrame
de cette manière.
N'y a-t-il aucun moyen d'obtenir ces informations - par ex. d'interroger le catalog
en ligne/temporaire pour la table registered
peut-être?
Mise à jour L'interface graphique Spark) montrait que l'opération DataFrame.rdd durait aussi longtemps que le sql le plus long du travail. I va réexécuter le travail et attacher la capture d'écran un peu ici.
Ce qui suit est juste un testcase: il utilise une petite fraction de la taille des données de celle en production. Le plus long sql
n'est que de cinq minutes - et celui-ci est sur le point de passer ce temps aussi (notez que le sql
est pas a aidé ici: il doit également s'exécuter par la suite, doublant ainsi efficacement le temps d'exécution cumulé).
Nous pouvons voir que le .rdd
l'opération à DataFrameUtils
ligne 30 (indiquée dans l'extrait ci-dessus) prend 5,1 minutes - et pourtant l'opération save
encore a pris 5,2 minutes plus tard -i.e. nous avons fait pas gagner du temps en faisant le .rdd
en termes de temps d'exécution du save
suivant.
Dans mon expérience df.rdd.getNumPartitions
est très rapide, je n'ai jamais rencontré cela plus d'une seconde environ.
Alternativement, vous pouvez également essayer
val numPartitions: Long = df
.select(org.Apache.spark.sql.functions.spark_partition_id()).distinct().count()
ce qui éviterait d'utiliser .rdd