Est groupByKey toujours préféré sur reduceByKey
J'ai toujours utiliser reduceByKey
quand j'en ai besoin pour regrouper les données en Rdd, car il effectue un coté carte de réduire avant de mélanger les données, ce qui signifie souvent que moins de données sont bousculés et j'ai ainsi obtenir de meilleures performances. Même lorsque la carte côté fonction de réduction rassemble toutes les valeurs et n'a pas réellement de réduire la quantité de données, j'utilise encore reduceByKey
, parce que je suis en supposant que le rendement de reduceByKey
ne sera jamais pire que groupByKey
. Cependant, je me demandais si cette hypothèse est correcte, ou si il y a en effet des situations où groupByKey
devraient être privilégiées??
groupByKey
est juste la syntaxe de sucre alors que @climbage pense que reduceByKey
peut-être un peu plus lent si je l'utilise pour reproduire groupByKey
fonctionnalité. Je pense que je vais effectivement essayer de tester les deux fonctions sur quelques exemples 🙂stackoverflow.com/questions/30825936/...
La seule fois où j'ai eu besoin d'utiliser groupByKey est pour les calculs sur des échantillons de données qui dépendent de la valeur précédente. Un précalculées total en cours d'exécution, en sont un exemple. La distance GPS. Etc.
OriginalL'auteur Glennie Helles Sindholt | 2015-10-19
Vous devez vous connecter pour publier un commentaire.
Je crois qu'il y a d'autres aspects du problème ignoré par climbage et eliasah:
Si l'opération n'est pas de réduire la quantité de données qu'il doit être d'une manière ou d'une autre sémantiquement équivalent à
GroupByKey
. Supposons que nous avonsRDD[(Int,String)]
:et nous voulons concaténer toutes les chaînes pour une clé donnée. Avec
groupByKey
, il est assez simple:Naïf solution avec
reduceByKey
ressemble à ceci:Il est court, et sans doute facile à comprendre, mais souffre de deux problèmes:
String
objet de tous les temps*De régler le premier problème que nous avons besoin d'une structure de données mutable:
Il suggère encore une autre chose qui se passe vraiment et est très longue, surtout si elle est répétée plusieurs fois dans votre script. Bien sûr, vous pouvez extraire les fonctions anonymes
mais à la fin de la journée, cela signifie encore plus d'effort pour comprendre ce code, d'une grande complexité, et sans réelle valeur ajoutée. Une chose que je trouve particulièrement troublant, c'est l'inclusion explicite de la mutable structures de données. Même si l'Étincelle poignées de presque toute la complexité, cela signifie que nous n'avons plus un élégant, referentially code transparent.
Mon point est que si vous avez vraiment réduire la quantité de données par tous les moyens l'utilisation
reduceByKey
. Sinon, vous rendre votre code plus difficile à écrire, plus difficile à analyser et à acquérir rien en retour.Note:
Cette réponse est axé sur la Scala
RDD
API. Actuelle de Python de la mise en œuvre est assez différente de ses JVM homologue et inclut des optimisations qui offrent d'importants avantages par rapport naïfreduceByKey
mise en œuvre en cas degroupBy
opérations.Pour
Dataset
API voir DataFrame /Dataset groupBy comportement/optimisation.* Voir L'étincelle de la performance pour la Scala vs Python pour un exemple convaincant
OriginalL'auteur zero323
reduceByKey
etgroupByKey
à la fois l'utilisationcombineByKey
avec différents combiner/fusionner sémantique.Ils principale différence que je vois, c'est que
groupByKey
passe le drapeau (mapSideCombine=false
) à la masse du moteur. À en juger par la question SPARK-772, c'est une allusion à la masse du moteur pour ne pas exécuter de la mapside combiner lorsque la taille des données n'est pas près de changer.Donc, je dirais que si vous essayez d'utiliser
reduceByKey
à reproduiregroupByKey
, vous pourriez voir un léger gain de performance.OriginalL'auteur Mike Park
Je ne vais pas inventer la roue, selon le code de la documentation, de la
groupByKey
fonctionnement des groupes de valeurs pour chaque clé dans la RDD dans une seule séquence qui permet également le contrôle de la répartition de la paire clé-valeur RDD par le passage d'unPartitioner
.Cette opération peut être très coûteux. Si vous êtes regroupement pour effectuer une agrégation (comme une somme ou une moyenne) au cours de chaque touche, en utilisant
aggregateByKey
oureduceByKey
offre de bien meilleures performances.Remarque: Comme actuellement mis en œuvre,
groupByKey
doit être en mesure de tenir toutes les paires clé-valeur pour n'importe quelle touche de la mémoire. Si une clé a trop de valeurs, il peut en résulter une OOME.Comme une question de fait, je préfère le
combineByKey
opération, mais il est parfois difficile de comprendre le concept de les combiner et de la fusion si vous n'êtes pas très familier avec la carte-réduire de paradigme. Pour cela, vous pouvez lire le yahoo map-reduce bible ici, ce qui explique bien ce sujet.Pour plus d'informations, je vous conseille de lire le PairRDDFunctions code.
Je comprends les problèmes possibles associés à
groupByKey
(comme trop de valeurs pour une clé donnée) - la question était de savoir si il ya des moments oùgroupByKey
est en fait le meilleur choix. Vous mentionnez que le partitionnement de la paire clé-valeur peut être contrôlé lors de l'utilisation degroupByKey
, mais il peut également être contrôlé avecreduceByKey
, donc ça ne semble pas être une raison pour l'utilisation degroupByKey
, ou suis-je malentendu vous?C'est tout à fait correct, vous pouvez envisager de
groupByKey
comme syntaxe de sucre. Si vous pouvez l'éviter, il est toujours préférable d'utiliser aggregateByKey,reduceByKey, ou combineByKeyvous ne semblez pas être convaincu.
Lors de l'utilisation
combineByKey
avecCompactBuffer
,+=
et++=
est exactement équivalente àgroupByKey
,combineByKey
vous permet de choisir le plus efficace de la structure de données basée sur des données de distribution. Sans doute il ya seulement une poignée de cas, quand on ne peut pas être remplacé par le repartitionnement et externe de tri mais il est plus probable que le faible niveau de l'approche pour un utilisateur ordinaire.OriginalL'auteur eliasah