2017-09-20 1 views
4

Es gibt einige gruselige Sprache in der Dokumentation von groupByKey, warnt, dass es "sehr teuer" sein kann, und schlägt vor, stattdessen aggregateByKey zu verwenden, wann immer es möglich ist.groupByKey vs. aggregateByKey - woher kommt der Unterschied?

Ich frage mich, ob der Unterschied in den Kosten von der Tatsache herrührt, dass für einige Aggregationen die gesamte Gruppe nie gesammelt und auf den gleichen Knoten geladen werden muss, oder wenn es andere Unterschiede bei der Implementierung gibt. Die Frage ist, ob rdd.groupByKey()rdd.aggregateByKey(Nil)(_ :+ _, _ ++ _) entspricht oder ob es immer noch teurer wäre.

+0

verwendet. Ich frage mich, ob der Unterschied in den Kosten von der Tatsache herrührt, dass für einige Aggregationen die gesamte Gruppe niemals gesammelt und auf denselben Knoten geladen werden muss. oder wenn es andere Unterschiede in der Durchführung gibt. "Genau –

+1

Die Leute, die stimmen, um zu schließen - sich interessieren, um zu erklären? "Nicht programmieren"? Hä? – Dima

+1

Behauptung: In den meisten Fällen ist 'rdd.groupByKey()' wesentlich billiger als 'rdd.aggregateByKey (Nil) (_: + _, _ ++ _)'. Ich habe diesen Punkt [hier] (https://stackoverflow.com/a/39316189/1560062) und mit @eliasah [hier] gemacht (https://github.com/awesome-spark/spark-gotchas/blob/master/ 04_rdd_actions_and_transformations_by_example.md # be-smart-about-groupbykey) (externer Link). – zero323

Antwort

4

Wenn Sie auf ein einzelnes Element anstatt auf eine Liste reduzieren.

Für zB: wie Wortanzahl dann aggregateByKey führt besser, weil es nicht shuffle verursachen wird, wie in der Verbindung performance of group by vs aggregate by erklärt.

Aber in Ihrem Fall verschmelzen Sie mit einer Liste. Im Falle von aggregateByKey werden zuerst alle Werte für einen Schlüssel in einer Partition auf eine einzelne Liste reduziert und dann die Daten für shuffle gesendet. Dies erzeugt so viele Listen wie Partitionen und der Speicher dafür wird hoch sein.

Im Falle von groupByKey erfolgt die Zusammenführung nur an einem Knoten, der für den Schlüssel verantwortlich ist. Die Anzahl der erstellten Listen beträgt hier nur eine pro Schlüssel. Im Fall der Zusammenführung zu Liste ist groupByKey in Bezug auf Speicher optimal.

siehe auch: SO Answer by zero323

Ich bin über Ihren Anwendungsfall nicht sicher.Aber wenn Sie die Anzahl der Elemente in der Liste im Endergebnis begrenzen können, wird sicherlich aggregateByKey/combineByKey im Vergleich zu groupByKey ein wesentlich besseres Ergebnis liefern. Für zB: Wenn Sie nur Top-10-Werte für einen bestimmten Schlüssel nehmen möchten. Dann könnte man dies effizient erreichen, indem man combineByKey with proper merge and combiner functions als groupByKey and take 10.

+0

Kann man davon ausgehen, dass die Vorteile von ByKey (kombinieren/aggregieren/reduzieren) nur dann richtig genutzt werden, wenn sich Daten auf mehreren Partitionen befinden und die verwendete Funktion als Combiner auf jeder Partition angewendet werden kann? – philantrovert

+0

Die Annahme ist richtig. Ich habe auch einen Anwendungsfall bereitgestellt, abgesehen davon, wo diese Operationen wirksam sind. Kurz gesagt, wenn Daten geschrumpft werden können, verwenden (aggregieren/reduzieren/kombinieren) ByKey. – Knight71

-1

Lassen Sie mich erläutern helfen, warum groupByKey Betrieb zu führen wird viel kosten

die semantische dieser speziellen Operation Durch das Verständnis, was die Aufgabe benötigen reduzieren mit einem zugehörigen zu tun ist, gruppieren Sie die ganze Werte einzelner eindeutiger Schlüssel.

Mit einem Wort, lassen Sie uns einen Blick auf sie Unterschrift ist

def groupByKey(): RDD[(K, Iterable[V])] 

Da der „groupby“ Betrieb alle mit diesem Schlüssel verknüpften Werte auf verschiedene Knoten partitioniert nicht prä- sein können verschmolzen. Große Datenübertragungen über das Netzwerk führen zu hoher Netzwerklast.

Aber aggregateByKey ist nicht das Gleiche mit ihm. Lassen Sie mich die Signatur klären:

def aggregateByKey[U](zeroValue: U)(seqOp: (U, V) ⇒ U, combOp: (U, U) ⇒ U)(implicit arg0: ClassTag[U]): RDD[(K, U)] 

Wie der Funke Motor dieses semantischen Betriebs implementieren ist wie folgt:

In Partition wird es vorge fusionierte Betrieb haben, bedeuten, dass „eine bestimmte Minderer“ brauchen nur um das gesamte vorgemischte Zwischenergebnis der Shuffle-Map zu holen.

Dadurch wird das Netzwerk erheblich heller.

+0

Sie scheinen also zu sagen, dass 'rdd.aggregateByKey (Nil) (_: + _, _ ++ _)' tatsächlich äquivalent zu 'rdd.grouByKey' ist. Recht? – Dima

+0

@Dima, absolut nicht. – ashburshui

+1

Dann verstehe ich nicht, was Sie sagen. Das Ergebnis meines Aggregats enthält alle Elemente für einen Schlüssel auf demselben Knoten. Ist nicht das, was du gesagt hast, die Kosten von 'groupBy' verursacht? – Dima