按列进行火花分区-内存爆炸

时间:2019-11-01 15:11:33

标签: java dataframe apache-spark dataset rdd

我正在尝试将实木复合地板按多列划分。为此,我首先通过一组函数(即-

)创建分区值
dataset.withColumn('p_year', functions.year(dataset.col('event_date')))
dataset.withColumn('p_month', functions.month(dataset.col('event_date')))
... etc

然后使用keyBy

对RDD进行分区
RDD<Tuple2<String, Row>> rddParts = dataset.rdd().keyBy(new BigDumbFunction());

...

class BigDumbFunction implements Function1<Row, String>, Serializable {

    private MySchema schema;

    public BigDumbFunction(MySchema schema) {
        this.schema = schema;
    }

    @Override
    public String apply(Row row) {
        StringBuilder stringBuilder = new StringBuilder();

        for(AbstractPartitionRule abstractPartitionRule: schema.getPartitionRules()) {
            String fieldName = abstractPartitionRule.getField();
            int fieldIndex = row.fieldIndex(fieldName);
            String value = row.getString(fieldIndex);

            stringBuilder.append(fieldName);
            stringBuilder.append("=");
            stringBuilder.append(value);
            stringBuilder.append("/");
        }

        return stringBuilder.substring(0, stringBuilder.length()-1);
    }
}

这将导致一个RDD元组,其中第一个值是分区值,第二个值是行。它实际上不是分组的,我必须手动执行-这使我认为keyBy是不适合使用的函数。

要对它们进行实际分组,我查看了所有行并按键对其进行排序-

JavaRDD<Tuple2<String, Row>> jrows = rddParts.toJavaRDD();
Map<String, List<Row>> siftedRows = new HashMap<>();

jrows.foreach((jrowTuple) -> {
    String partitionName = jrowTuple._1();
    Row rowData = jrowTuple._2();

    if (!siftedRows.containsKey(partitionName)) {
        siftedRows.put(partitionName, new ArrayList<>());
    }
    siftedRows.get(partitionName).add(rowData);
});

在此处执行foreachcollect会将内存消耗到1gb或更多。我假设这是因为我将其添加到无法与RDD进行相同优化的Map中。

如何用内存最少的多列进行分区?我可以使用所有分区值构建单个分区列,并按不同进行过滤吗?

0 个答案:

没有答案
相关问题