Quelqu'un peut-il expliquer la différence entre reductionbykey, groupbykey, aggregbykey et combinebykey? J'ai lu les documents à ce sujet, mais je ne pouvais pas comprendre les différences exactes?
Si vous pouvez l'expliquer avec des exemples, ce serait formidable.
groupByKey:
Syntaxe:
sparkContext.textFile("hdfs://")
.flatMap(line => line.split(" ") )
.map(Word => (Word,1))
.groupByKey()
.map((x,y) => (x,sum(y)) )
groupByKey peut provoquer des problèmes de disque car les données sont envoyées sur le réseau et collectées sur les postes de travail réduits.
reductionByKey:
Syntaxe:
sparkContext.textFile("hdfs://")
.flatMap(line => line.split(" "))
.map(Word => (Word,1))
.reduceByKey((x,y)=> (x+y))
Les données sont combinées sur chaque partition, une seule sortie pour une clé sur chaque partition étant envoyée sur le réseau . reductionByKey est nécessaire pour combiner toutes vos valeurs dans une autre valeur du même type.
aggregByKey:
idem que reductionByKey, qui prend une valeur initiale.
3 paramètres en entrée I. valeur initiale ii. Logique du combinateur iii. logique de séquence
*Example:* `
val keysWithValuesList = Array("foo=A", "foo=A", "foo=A", "foo=A", "foo=B", "bar=C", "bar=D", "bar=D")
val data = sc.parallelize(keysWithValuesList)
//Create key value pairs
val kv = data.map(_.split("=")).map(v => (v(0), v(1))).cache()
val initialCount = 0;
val addToCounts = (n: Int, v: String) => n + 1
val sumPartitionCounts = (p1: Int, p2: Int) => p1 + p2
val countByKey = kv.aggregateByKey(initialCount)(addToCounts, sumPartitionCounts)
`
ouput: Agréger par somme de résultats Résultatsbar -> 3foo -> 5
combineByKey:
3 paramètres en entrée
Exemple: `
val result = rdd.combineByKey(
(v) => (v,1),
( (acc:(Int,Int),v) => acc._1 +v , acc._2 +1 ) ,
( acc1:(Int,Int),acc2:(Int,Int) => (acc1._1+acc2._1) , (acc1._2+acc2._2))
).map( { case (k,v) => (k,v._1/v._2.toDouble) })
result.collect.foreach(println)
`
reductionByKey, aggregByKey, combineByKey préféré sur groupByKey
Référence:Eviter groupByKey
Tandis que les commandes de réduction de clé et de groupe permettent de produire la même réponse, le Réduire exemple exemple fonctionne mieux sur un grand ensemble de données. C'est car Spark sait qu’il peut combiner la sortie avec une clé commune sur chaque partitionner avant de mélanger les données.
Par ailleurs, lorsque vous appelez groupByKey, toutes les paires clé-valeur sont mélangés. Cela fait beaucoup de données inutiles à être transféré sur le réseau.
pour plus de détails, consultez ce lien ci-dessous
groupByKey()
consiste simplement à grouper votre jeu de données en fonction d'une clé. Cela entraînera un brassage des données lorsque le RDD n’est pas déjà partitionné. reduceByKey()
est quelque chose comme grouper + agrégation. Nous pouvons dire réducteur équivalent () à dataset.group (...). Réduire (...). Il mélangera moins de données contrairement à groupByKey()
. aggregateByKey()
est logiquement identique à reductionByKey () mais vous permet de renvoyer le résultat dans un type différent. En d'autres termes, il vous permet d'avoir une entrée de type x et d'agréger le résultat de type y. Par exemple (1,2), (1,4) en entrée et (1, "six") en sortie. Il faut aussi zero-value qui sera appliqué au début de chaque touche.Remarque: Une similitude est qu'ils sont tous des opérations larges.
Bien que les deux obtiennent les mêmes résultats, il existe une différence significative dans les performances des deux fonctions. reduceByKey()
fonctionne mieux avec des jeux de données plus volumineux par rapport à groupByKey()
.
Dans reduceByKey()
, les paires d'un même ordinateur possédant la même clé sont combinées (à l'aide de la fonction passée à reduceByKey()
) avant que les données ne soient mélangées. Ensuite, la fonction est appelée à nouveau pour réduire toutes les valeurs de chaque partition afin de produire un résultat final.
Dans groupByKey()
, toutes les paires clé-valeur sont mélangées. Cela représente beaucoup de données inutiles à transférer sur le réseau.
ReduceByKeyreduceByKey(func, [numTasks])
-
Les données sont combinées de manière à ce qu'il y ait au moins une valeur pour chaque clé sur chaque partition .
GroupByKey - groupByKey([numTasks])
Il ne fusionne pas les valeurs de la clé, mais directement le processus de mélange a lieu Ici, de nombreuses données sont envoyées à chaque partition, presque identiques aux données initiales.
Et la fusion des valeurs pour chaque clé est effectuée après la lecture aléatoire . Ici, de nombreuses données stockées sur le noeud de travail final entraînent un problème de mémoire insuffisante.
AggregateByKey - aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])
Il ressemble à reductionByKey, mais vous pouvez fournir des valeurs initiales lors de l'agrégation.
Utilisation de reduceByKey
reduceByKey
peut être utilisé lorsque nous exécutons de grands ensembles de données.
reduceByKey
lorsque les types de valeur d'entrée et de sortie sont du même type sur aggregateByKey
De plus, il est recommandé de ne pas utiliser groupByKey
et de préférer reduceByKey
. Pour plus de détails, vous pouvez consulter ici .
Vous pouvez également consulter cette question pour comprendre plus en détail comment reduceByKey
et aggregateByKey
.
Alors en dehors de ces 4, nous avons
foldByKey qui est identique à reductionByKey mais avec une valeur zéro définie par l'utilisateur.
AggregateByKey prend 3 paramètres en entrée et utilise 2 fonctions pour la fusion (une pour la fusion sur les mêmes partitions et une autre pour la fusion de valeurs sur plusieurs partitions. Le premier paramètre est ZeroValue).
tandis que
RéduireBykey prend 1 paramètre seulement qui est une fonction pour la fusion.
CombineByKey prend 3 paramètres et tous les 3 sont des fonctions. Semblable à aggregBykey sauf qu'il peut avoir une fonction pour ZeroValue.
GroupByKey ne prend aucun paramètre et regroupe tout. En outre, il s'agit d'une surcharge pour le transfert de données entre partitions.