miarę Mogę powiedzieć, że nie ma nic do zyskania * w tym konkretnym przypadku przy użyciu aggregateByKey
lub podobnej funkcji. Ponieważ budujesz listę, nie ma "prawdziwej" redukcji, a ilość danych, które trzeba przetasować, jest mniej więcej taka sama.
Aby naprawdę zaobserwować pewne zwiększenie wydajności, potrzebne są transformacje, które faktycznie zmniejszają ilość przekazywanych danych, na przykład zliczanie, obliczanie statystyk podsumowujących, wyszukiwanie unikatowych elementów.
Odnośnie różnic zalet korzystania reduceByKey()
, combineByKey()
lub foldByKey()
istnieje istotna różnica koncepcyjna, która jest lepiej widoczny, gdy uznają Scala singatures API.
Zarówno reduceByKey
, jak i foldByKey
mapa od RDD[(K, V)]
do RDD[(K, V)]
, podczas gdy druga zapewnia dodatkowy element zerowy.
reduceByKey(func: (V, V) ⇒ V): RDD[(K, V)]
foldByKey(zeroValue: V)(func: (V, V) ⇒ V): RDD[(K, V)]
combineByKey
(nie ma aggregateByKey
, ale jest to ten sam typ transformacji) przekształca od RDD[(K, V)]
do RDD[(K, C)]
:
combineByKey[C](
createCombiner: (V) ⇒ C,
mergeValue: (C, V) ⇒ C,
mergeCombiners: (C, C) ⇒ C): RDD[(K, C)]
Wracając do przykładu combineByKey
(aw PySpark aggregateByKey
) jest naprawdę obowiązujące od czasu transformacji z RDD[(String, Int)]
do RDD[(String, List[Int])]
.
Choć w dynamicznym języku Python jak to jest faktycznie możliwe do przeprowadzenia takiej operacji przy użyciu foldByKey
lub reduceByKey
to sprawia, że semantyka kodu niejasne i cytować @ Tim-Peters „Nie powinno być jedno- i korzystnie tylko jeden - czysty sposób na zrobienie tego: "[1].
Różnica między aggregateByKey
i combineByKey
jest prawie taka sama jak między reduceByKey
i foldByKey
więc na liście najczęściej jest to kwestia gustu:
def merge_value(acc, x):
acc.append(x)
return acc
def merge_combiners(acc1, acc2):
acc1.extend(acc2)
return acc1
rdd = (sc.parallelize([("a", 7), ("b", 3), ("a", 8)])
.combineByKey(
lambda x: [x],
lambda u, v: u + [v],
lambda u1,u2: u1+u2))
W praktyce powinno wolisz groupByKey
chociaż. Implementacja PySpark jest znacznie bardziej zoptymalizowana w porównaniu do implementacji naiwnej, takiej jak przedstawiona powyżej.
1.Peters, T. PEP 20 - The Zen of Python. (2004). w https://www.python.org/dev/peps/pep-0020/
* W praktyce nie jest całkiem dużo do stracenia tutaj, zwłaszcza przy użyciu PySpark. Implementacja Pythona groupByKey
jest znacznie bardziej zoptymalizowana niż naiwna kombinacja przez klucz. Możesz sprawdzić Be Smart About groupByKey, utworzony przeze mnie i @eliasah dla dodatkowej dyskusji.
Czy dane są podzielone losowo, czy według klucza? Jeśli możesz upewnić się, że wszystkie rekordy z a._1 = "a" są na tej samej partycji, możesz znacznie przyspieszyć rzeczy - możesz być w stanie uciec bez potrzeby tasowania innych niż te potrzebne do początkowego partycjonowania . Może spróbuj użyć partycjonera mieszającego? –