web-dev-qa-db-fra.com

Comptez sur Spark Dataframe est extrêmement lent

Je crée un nouveau DataFrame avec une poignée d'enregistrements d'une jointure.

val joined_df = first_df.join(second_df, first_df.col("key") ===
second_df.col("key") && second_df.col("key").isNull, "left_outer")
joined_df.repartition(1)
joined_df.cache()
joined_df.count()

Tout est rapide (moins d'une seconde) sauf l'opération de comptage. La conversion RDD entre en action et prend littéralement des heures pour se terminer. Existe-t-il un moyen d'accélérer les choses?

INFO MemoryStore: Block rdd_63_140 stored as values in memory (estimated size 16.0 B, free 829.3 MB)
INFO BlockManagerInfo: Added rdd_63_140 in memory on 192.168.8.52:36413 (size: 16.0 B, free: 829.8 MB)
INFO Executor: Finished task 140.0 in stage 10.0 (TID 544). 4232 bytes result sent to driver
INFO TaskSetManager: Starting task 142.0 in stage 10.0 (TID 545, localhost, executor driver, partition 142, PROCESS_LOCAL, 6284 bytes)
INFO Executor: Running task 142.0 in stage 10.0 (TID 545)
INFO TaskSetManager: Finished task 140.0 in stage 10.0 (TID 544) in 16 ms on localhost (executor driver) (136/200)
INFO ShuffleBlockFetcherIterator: Getting 0 non-empty blocks out of 200 blocks
INFO ShuffleBlockFetcherIterator: Started 0 remote fetches in 0 ms
INFO ShuffleBlockFetcherIterator: Getting 0 non-empty blocks out of 200 blocks
INFO ShuffleBlockFetcherIterator: Started 0 remote fetches in 0 ms
7
br0ken.pipe

Tout est rapide (moins d'une seconde) sauf l'opération de comptage.

Ceci est justifié comme suit: toutes les opérations avant les count sont appelées transformations et ce type d'opérations spark sont paresseux c'est-à-dire qu'il ne fait aucun calcul avant d'appeler une action (count dans votre exemple).

Le deuxième problème est dans la repartition(1):

gardez à l'esprit que vous perdrez tout le parallélisme offert par spark et votre calcul sera exécuté dans un exécuteur (noyau si vous êtes en mode autonome), vous devez donc supprimer cette étape ou modifier 1 à un nombre propositionnel au nombre de cœurs de votre CPU (mode autonome) ou au nombre d'exécuteurs (mode cluster).

La conversion RDD entre en jeu et prend littéralement des heures pour se terminer.

Si je comprends bien, vous convertiriez le DataFrame en RDD, c'est vraiment une mauvaise pratique dans spark et vous devriez éviter une telle conversion aussi possible que vous c'est parce que les données dans DataFrame et Dataset sont encodées en utilisant special spark encoders (ça s'appelle tungstant si je s'en souviennent) qui prennent beaucoup moins de mémoire que les encodeurs de sérialisation JVM, donc une telle conversion signifie que spark changera le type de vos données par les siens (qui prennent beaucoup moins de mémoire) et laissez spark optimiser beaucoup de commutations en travaillant simplement les données encodées et non en sérialisant les données avec lesquelles travailler et puis en les désérialisant) vers les données JVM tapez et c'est pourquoi DataFrames et Datasets sont très puissants que RDDs

J'espère que cela vous aidera

22
Haroun Mohammedi

Comme d'autres l'ont mentionné, les opérations avant count sont "paresseuses" et seules enregistrent une transformation , plutôt qu'en réalité force un calcul .

Lorsque vous appelez count, le calcul est déclenché. C'est lorsque Spark lit vos données, effectue toutes les transformations précédemment enregistrées et calcule le résultat que vous avez demandé (dans ce cas, un count).

La conversion RDD démarre et prend littéralement des heures

Je pense que le terme "conversion" est peut-être un peu inexact. Ce qui se passe réellement, c'est que les transformations DataFrame que vous avez enregistrées sont traduites en opérations RDD, et elles sont appliquées au RDD qui sous-tend votre DataFrame. Il n'y a pas de conversion en soi dans le code que vous avez donné ici.

En passant, il est possible de convertir explicitement un DataFrame en RDD via le DataFrame.rdd propriété. Comme mentionné dans cette réponse c'est généralement une mauvaise idée, car vous perdez certains des avantages (à la fois en termes de performances et d'API) d'avoir des données bien structurées.

1
timchap