具有自连接功能的Spark sql笛卡尔积

时间:2019-11-10 08:52:12

标签: apache-spark apache-spark-sql parquet

我有一个用例,我需要在给定类别中的每个项目上运行自定义算法,并且对于每个项目,从算法中找到前10个结果并将其存储。 我在这里发布了一个单独的问题,关于groupBy操作的性能含义: Spark SQL - group by after repartitioning

但是,假设我已经能够将列表中给定类别的所有项目分组。输出看起来像这样:

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

让我们假设每个类别在id列表中可以包含数百万个项目。因此,可以有效地将其视为id列表中的笛卡尔乘积。

我要做的一件事情是做一个flatmap()并为每个category-idm-idn组合创建1行。这是该代码:

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         |
+---------------+------------+------------+

基本上,每个商品ID和每个类别的其他所有商品ID。虽然这可以工作,但确实会使数据膨胀。正如我最初提到的,我们每个类别可以有100万个项目,因此,在某些情况下,上述代码可能会为每个类别生成100万乘100万行,这确实使数据膨胀。 因此,想了解如何最佳地优化这类笛卡尔积方案。 是否会为每个id创建一个新列并以列格式(例如镶木地板)存储它们,然后逐列运行计算,这是一种更好的处理方式?

0 个答案:

没有答案