web-dev-qa-db-fra.com

Comment vérifier le nombre de partitions d'un Spark DataFrame sans encourir le coût de .rdd

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é).

enter image description here

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.

6
javadba

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

2
Raphael Roth