Альтернатива groupBy в Spark - PullRequest
0 голосов
/ 04 июня 2018

У меня есть Dataframe df со следующей информацией:

id   json_data
1    {a: "1", b: "2"} 
1    {a: "1", b: "3"} 
1    {a: "1", b: "4"}
2    {a: "1", b: "2"} 
2    {a: "1", b: "6"}

И мне нужен следующий конечный результат:

id   json_data
1    [{a: "1", b: "2"},{a: "1", b: "3"},{a: "1", b: "4"}]
2    [{a: "1", b: "2"},{a: "1", b: "6"}]

Я пробовал два разных подхода, используя функции Window и groupBy соответственно,При обоих подходах я получаю желаемый результат.

1º подход:

var user_window = Window.partitionBy("id").orderBy("id")
val df2 = df.withColumn("json_data",
    collect_list($"json_data").over(user_window))
          .withColumn("rank", row_number().over(user_window))
          .where("rank = 1")

2º подход:

val df2 = df.groupBy(df("id")).agg(collect_list($"json_data").as("json_data"))

При обоих подходах я получаю одинаковую производительность.Но, читая документацию о Spark, кажется, что оба подхода неэффективны, так как строки с одним и тем же ключом должны перемещаться по кластеру (перемешиваться), чтобы быть вместе.Я показываю небольшой пример, потому что в производстве у меня большой объем данных.И выполнение группы или использование оконных функций занимает много времени.

Есть ли альтернативы для этого?

1 Ответ

0 голосов
/ 04 июня 2018

Мой совет будет использовать reduByKey.

Таким образом, если ваш ключ равен id, а ваше значение (в начале) равно json_data в списке, затем выполняется reduByKey вместе с конкатенациейФункция, из различных json_data упакованных списков, даст вам лучшую производительность.

В двух словах, при использовании reduByKey сначала выполняется «groupBy» внутри раздела, и только после этого начинается перетасовка данных.

Хорошее место для прочтения различий в производительности groupByKey и reduceByKey: здесь (part 6b).

В pyspark это будет выглядеть так:

rdd = df.rdd
rdd = rdd.map(lambda row: (row['id'], [row['json_data']]))
rdd = rdd.reduceByKey(lambda a, b: a + b)
...