¿Quién puede dar una explicación clara para `combineByKey` en Spark?

Estoy aprendiendo chispa, pero no puedo entender esta función combineByKey .

 >>> data = sc.parallelize([("A",1),("A",2),("B",1),("B",2),("C",1)] ) >>> data.combineByKey(lambda v : str(v)+"_", lambda c, v : c+"@"+str(v), lambda c1, c2 : c1+c2).collect() 

La salida es:

 [('A', '1_2_'), ('C', '1_'), ('B', '1_2_')] 

Primero, estoy muy confundido: ¿dónde está la @ en el segundo paso lambda c, v : c+"@"+v ? No puedo encontrar @ del resultado.

En segundo lugar, leí la descripción de la función para combineByKey , pero estoy confundido con el flujo del algoritmo.

La llamada groupByKey no intenta fusionar / combinar valores, por lo que es una operación costosa.

Por lo tanto, la llamada combineByKey es una optimización de este tipo. Cuando se usan los valores de combineByKey se combinan en un valor en cada partición, entonces cada valor de partición se combina en un solo valor. Vale la pena señalar que el tipo del valor combinado no tiene que coincidir con el tipo del valor original y muchas veces no lo será. La función combineByKey toma 3 funciones como argumentos:

  1. Una función que crea un combinador. En la función aggregateByKey , el primer argumento fue simplemente un valor inicial de cero. En combineByKey proporcionamos una función que aceptará nuestro valor actual como parámetro y devolverá nuestro nuevo valor que se fusionará con valores adicionales.

  2. La segunda función es una función de fusión que toma un valor y la combina / combina en los valores recostackdos anteriormente.

  3. La tercera función combina los valores combinados juntos. Básicamente, esta función toma los nuevos valores producidos en el nivel de partición y los combina hasta que obtengamos un valor singular.

En otras palabras, para entender combineByKey , es útil pensar cómo maneja cada elemento que procesa. A medida que combineByKey recorre los elementos de una partición, cada elemento tiene una clave que no ha visto antes o tiene la misma clave que un elemento anterior.

Si es un elemento nuevo, combineByKey usa una función que proporcionamos, llamada createCombiner() , para crear el valor inicial para el acumulador en esa clave. Es importante tener en cuenta que esto sucede la primera vez que se encuentra una clave en cada partición, en lugar de solo la primera vez que se encuentra la clave en el RDD.

Si es un valor que hemos visto antes al procesar esa partición, en su lugar usará la función proporcionada, mergeValue() , con el valor actual del acumulador para esa clave y el nuevo valor.

Como cada partición se procesa de forma independiente, podemos tener múltiples acumuladores para la misma clave. Cuando combinamos los resultados de cada partición, si dos o más particiones tienen un acumulador para la misma clave, combinamos los acumuladores utilizando la función mergeCombiners() proporcionada por el usuario.

Referencias:

  • Learning Spark – Capítulo 4 .
  • Usando combineByKey en la entrada del blog Apache-Spark .

‘@’ solo se agrega dentro de cada partición. En su ejemplo, parece que solo hay un elemento en cada partición. Tratar:

 data.combineByKey(lambda v : str(v)+"_", lambda c, v : c+"@"+str(v), lambda c1, c2 : c1+'$'+c2).collect() $ 

y ver la diferencia