我正在尝试将实木复合地板按多列划分。为此,我首先通过一组函数(即-
)创建分区值dataset.withColumn('p_year', functions.year(dataset.col('event_date')))
dataset.withColumn('p_month', functions.month(dataset.col('event_date')))
... etc
然后使用keyBy
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);
});
在此处执行foreach
或collect
会将内存消耗到1gb或更多。我假设这是因为我将其添加到无法与RDD进行相同优化的Map中。
如何用内存最少的多列进行分区?我可以使用所有分区值构建单个分区列,并按不同进行过滤吗?