Декартово произведение Spark sql с самостоятельным соединением - PullRequest
0 голосов
/ 10 ноября 2019

У меня есть сценарий использования, в котором мне нужно запустить собственный алгоритм для каждого элемента в данной категории и для каждого элемента найти 10 лучших результатов этого алгоритма и сохранить их. Я разместил отдельный вопрос о том, как влияет на производительность операция groupBy: Spark SQL - group by после перераспределения

Но, скажем, я смог сгруппировать все элементы дляданная категория в списке. Вывод выглядит так:

+---------------------------+------------------------------------------+
|category                   |     ids                                  |
+---------------------------+------------------------------------------+
|category-1                 | [id1, id2...]                            |
|category-2                 | [idx, idy...]                            |
+---------------------------+------------------------------------------+

Предположим, что каждая категория может иметь миллионы элементов в списке идентификаторов. Таким образом, фактически это можно рассматривать как декартово произведение в списке идентификаторов.

Одна из вещей, которые я сделал, - это создание flatmap () и создание 1 строки для каждой комбинации category-idm-idn. Вот код для этого:

Dataset<Row> wpid_cartesian_product_by_category = ids_grouped_by_category.flatMap((FlatMapFunction<Row, Row>) row -> {
            List<Row> category_all_ids_combination = new ArrayList<>();
            String category = row.getString(0);
            List<String> all_ids_for_category = row.getList(1);
            for (int i = 0; i < all_ids_for_category.size(); i++){
                String itemid1 = all_ids_for_category.get(i);
                for (int j = 0; j < all_ids_for_category.size(); j++) {
                    if (i == j)
                        continue;
                    Row cartesian_product_row = RowFactory.create(category, id1, all_ids_for_category.get(j));
                    category_all_ids_combination.add(cartesian_product_row);
                }
            }
            return category_all_ids_combination.iterator();
        }, <encoder>);

Благодаря этому я смог получить новый набор данных, такой как:

+---------------+------------+------------+
|category       |id_1        |id_2        |
+---------------+------------+------------+
|category-1     |id1         |id2         |
|category-1     |id1         |id3         |
|category-1     |id2         |id1         |
+---------------+------------+------------+

В основном каждый идентификатор элемента с каждым другим идентификатором элемента в категории. Хотя это может сработать, но это действительно будет раздувать данные. Как я уже упоминал ранее, у нас может быть 1 миллион элементов на категорию, поэтому может существовать сценарий, в котором приведенный выше код может генерировать строки размером 1 миллион на 1 миллион для каждой категории, что на самом деле увеличивает объем данных. Итак, я хотел понять, как лучше оптимизировать эти виды сценариев декартовых произведений. Будет ли создание нового столбца для каждого идентификатора и сохранение их в столбчатом формате (скажем, паркет), а затем запуск вычисления столбец за столбцом лучшим способом для этого?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...