Selon Learning Spark
N'oubliez pas que la répartition de vos données est une opération assez coûteuse . Spark dispose également d’une version optimisée de repartition () appelée coalesce (), qui permet d’éviter le transfert de données, mais uniquement si vous réduisez le nombre de partitions RDD.
Une différence que j’obtiens est que, avec repartition (), le nombre de partitions peut être augmenté/diminué, mais avec coalesce (), le nombre de partitions ne peut être que diminué.
Si les partitions sont réparties sur plusieurs machines et que coalesce () est exécuté, comment peut-il éviter le transfert de données?
Il évite un plein shuffle. Si l'on sait que le nombre diminue, alors l'exécutant peut conserver en toute sécurité des données sur le nombre minimum de partitions, en déplaçant uniquement les données des nœuds supplémentaires vers les nœuds que nous avons conservés.
Donc, ça donnerait quelque chose comme ça:
Node 1 = 1,2,3
Node 2 = 4,5,6
Node 3 = 7,8,9
Node 4 = 10,11,12
Puis coalesce
jusqu'à 2 partitions:
Node 1 = 1,2,3 + (10,11,12)
Node 3 = 7,8,9 + (4,5,6)
Notez que les nœuds 1 et 3 ne nécessitent pas le déplacement de leurs données d'origine.
La réponse de Justin est géniale et cette réponse va plus en profondeur.
L'algorithme repartition
effectue un brassage complet et crée de nouvelles partitions avec des données réparties uniformément. Créons un DataFrame avec les nombres de 1 à 12.
val x = (1 to 12).toList
val numbersDf = x.toDF("number")
numbersDf
contient 4 partitions sur ma machine.
numbersDf.rdd.partitions.size // => 4
Voici comment les données sont divisées sur les partitions:
Partition 00000: 1, 2, 3
Partition 00001: 4, 5, 6
Partition 00002: 7, 8, 9
Partition 00003: 10, 11, 12
Faisons un shuffle complet avec la méthode repartition
et obtenons ces données sur deux nœuds.
val numbersDfR = numbersDf.repartition(2)
Voici comment les données numbersDfR
sont partitionnées sur ma machine:
Partition A: 1, 3, 4, 6, 7, 9, 10, 12
Partition B: 2, 5, 8, 11
La méthode repartition
crée de nouvelles partitions et distribue les données de manière uniforme dans les nouvelles partitions (la distribution des données est plus uniforme pour les grands ensembles de données).
Différence entre coalesce
et repartition
coalesce
utilise des partitions existantes pour minimiser la quantité de données brassées. repartition
crée de nouvelles partitions et effectue un shuffle complet. coalesce
donne des partitions avec différentes quantités de données (parfois des partitions de tailles très différentes) et repartition
donne des partitions de taille à peu près égale.
Est-ce que coalesce
ou repartition
est plus rapide?
coalesce
peut s'exécuter plus rapidement que repartition
, mais les partitions de taille différente sont généralement plus lentes à utiliser que des partitions de taille égale. Vous aurez généralement besoin de repartitionner les jeux de données après avoir filtré un jeu de données volumineux. J'ai constaté que repartition
était globalement plus rapide, car Spark est conçu pour fonctionner avec des partitions de taille égale.
Lisez cet article de blog si vous souhaitez plus de détails.
Un point supplémentaire à noter ici est que, comme principe de base de Spark RDD est l’immuabilité. La répartition ou la fusion créera un nouveau RDD. Le RDD de base continuera d'exister avec le nombre de partitions d'origine. Si le cas d'utilisation demande de conserver le RDD dans le cache, il en va de même pour le nouveau RDD créé.
scala> pairMrkt.repartition(10)
res16: org.Apache.spark.rdd.RDD[(String, Array[String])] =MapPartitionsRDD[11] at repartition at <console>:26
scala> res16.partitions.length
res17: Int = 10
scala> pairMrkt.partitions.length
res20: Int = 2
Toutes les réponses ajoutent de grandes connaissances à cette question très souvent posée.
Donc, suivant la chronologie de cette question, voici mes 2 centimes.
J'ai trouvé la partition plus rapide que la fusion , dans des cas très spécifiques.
Dans mon application, lorsque le nombre de fichiers que nous estimons est inférieur au seuil défini, la répartition se fait plus rapidement.
Voici ce que je veux dire
if(numFiles > 20)
df.coalesce(numFiles).write.mode(SaveMode.Overwrite).parquet(dest)
else
df.repartition(numFiles).write.mode(SaveMode.Overwrite).parquet(dest)
Dans l'extrait ci-dessus, si mes fichiers étaient inférieurs à 20, la fusion prenait une longueur indéterminée tandis que la répartition était beaucoup plus rapide et le code ci-dessus.
Bien entendu, ce nombre (20) dépendra du nombre de travailleurs et de la quantité de données.
J'espère que cela pourra aider.
Ce qui découle du code et de la documentation est que coalesce(n)
est identique à coalesce(n, shuffle = false)
et repartition(n)
est identique à coalesce(n, shuffle = true)
.
Ainsi, coalesce
et repartition
peuvent être utilisés pour augmenter le nombre de partitions.
Avec shuffle = true, vous pouvez fusionner un plus grand nombre de partitions. Ceci est utile si vous avez un petit nombre de partitions, disons 100, potentiellement avec quelques partitions anormalement grandes.
Une autre remarque importante à souligner est que si vous diminuez considérablement le nombre de partitions, vous devriez envisager d’utiliser la version shuffled . de coalesce
(identique à repartition
dans ce cas). Cela permettra d'effectuer vos calculs en parallèle sur les partitions parentes (tâche multiple).
Toutefois, si vous effectuez une fusion drastique, par exemple Pour numPartitions = 1, votre calcul peut avoir lieu sur moins de nœuds que vous le souhaitez (par exemple, un nœud dans le cas où numPartitions = 1). Pour éviter cela, vous pouvez passer shuffle = true. Cela ajoutera une étape de lecture aléatoire, mais signifie que les partitions en amont actuelles seront exécutées en parallèle (quelle que soit la partition en cours).
Veuillez également vous reporter à la réponse associée ici
repartition
- il est recommandé d’utiliser la répartition tout en augmentant le nombre de partitions, car il implique un brassage de toutes les données.
coalesce
- il est recommandé d’utiliser coalesce tout en réduisant le nombre de partitions. Par exemple, si vous avez 3 partitions et que vous voulez le réduire à 2 partitions, Coalesce déplacera les données de la 3e partition vers les partitions 1 et 2. Les partitions 1 et 2 resteront dans le même conteneur. entre exécuteur sera élevé et cela influe sur la performance.
Performance sage coalesce
performance meilleure que repartition
tout en réduisant le nombre de partitions.
De manière simple COALESCE: - sert uniquement à réduire le nombre de partitions, le brassage des données ne fait que compresser les partitions
REPARTITION: - est à la fois pour augmenter et diminuer le nombre de partitions, mais le brassage a lieu
Exemple:-
val rdd = sc.textFile("path",7)
rdd.repartition(10)
rdd.repartition(2)
Les deux fonctionne bien
Mais nous allons généralement pour ces deux choses lorsque nous avons besoin de voir la sortie dans un cluster, nous allons avec ceci.
Toute la bonne réponse que je voudrais ajouter est que la re-partition est l’une des meilleures options pour tirer parti de la parallélisation des données et que la fusion permet de réduire le coût de la partition et est très utile lors de l’écriture de données sur HDFS ou un autre écrit. J'ai trouvé cela utile lors de l'écriture de données au format parquet pour en tirer le meilleur parti.
Mais vous devez également vous assurer que les données qui arrivent sont des nœuds de coalescence hautement configurés, si vous traitez avec d’énormes données. Étant donné que toutes les données seront chargées sur ces nœuds, une exception de mémoire peut se produire . Bien que la réparation soit coûteuse, je préfère l’utiliser. Depuis, il mélange et distribue les données de manière égale.
Soyez sage de choisir entre la fusion et la répartition.
Pour ceux qui rencontraient des problèmes, générer un fichier csv unique à partir de PySpark (AWS EMR) et le sauvegarder sur s3, l’utilisation de la repartition aidait. La raison en est que la fusion ne peut pas être un mélange complet, mais la répartition peut. Pour résumer, vous pouvez augmenter ou réduire le nombre de partitions utilisant la répartition, mais vous ne pouvez que réduire le nombre de partitions (mais pas 1) utilisant la fusion. Voici le code pour quiconque tente d'écrire un fichier CSV d'AWS EMR vers s3:
df.repartition(1).write.format('csv')\
.option("path", "s3a://my.bucket.name/location")\
.save(header = 'true')
J'aimerais ajouter à la réponse de Justin et Power que -
"repartitionner" ignorera les partitions existantes et en créera de nouvelles. Vous pouvez donc l'utiliser pour corriger le biais des données. Vous pouvez mentionner des clés de partition pour définir la distribution. L'inégalité des données est l'un des problèmes les plus importants dans le domaine des «données volumineuses».
"coalesce" fonctionnera avec les partitions existantes et en mélangera un sous-ensemble. Il ne peut pas corriger l'inclinaison des données autant que la "répartition" le peut. alors même si c'est moins cher, ce n'est peut-être pas ce dont vous avez besoin.