我使用的是Flink1.4.0。
假设我有一个POJO,如下所示:
public class Rating {
public String name;
public String labelA;
public String labelB;
public String labelC;
...
}
以及 join函数:
public class SetLabelA implements JoinFunction, Tuple2, Tuple2> {
@Override
public Tuple2<String, Rating> join(Tuple2<String, Rating> rating, Tuple2<String, String> labelA) {
rating.f1.setLabelA(labelA)
return rating;
}
}
假设我想应用一个JOIN操作来设置DataSet>中每个字段的值,我可以这样做:
DataSet> ratings = // [...]
DataSet> aLabels = // [...]
DataSet> bLabels = // [...]
DataSet> cLabels = // [...]
...
DataSet>
newRatings =
ratings.leftOuterJoin(aLabels, JoinOperatorBase.JoinHint.REPARTITION_SORT_MERGE)
// key of the first input
.where("f0")
// key of the second input
.equalTo("f0")
// applying the JoinFunction on joining pairs
.with(new SetLabelA());
不幸的是,这是必要的,因为评级和所有xlabel都是非常大的 DataSet ,我被迫查看每个xlabel以找到我需要的字段值,但同时并非所有的评级 key都存在于每个xlabel中。
这实际上意味着我必须为每个xlabel执行一个leftOuterJoin,为此我还需要创建相应的JoinFunction实现,该实现使用来自评级POJO的正确setter。
有没有更有效的方法来解决这个问题,任何人都能想到?
至于分区策略,我已经确保将 DataSet >的评级排序为:
DataSet> sorted_ratings = ratings.sortPartition(0, Order.ASCENDING).setParallelism(1);
通过将parallelism设置为1,我可以确定整个 DataSet 将被排序。然后使用.partitionByRange:
DataSet> partitioned_ratings = sorted_ratings.partitionByRange(0).setParallelism(N);
我的核数是。另一个附带的问题是,设置为1的第一个.setparallellelism是否限制了 pipeline 其余部分的执行方式,即follow.setParallelism(N)是否可以更改 DataSet 的处理方式?
最后,我做了所有这些,这样当分区的评等与xlabels DataSet join时,JOIN操作将使用JoinOperatorBase.JoinHint.REPARTITION_SORT_MERGE. root据Flink针对v.1.4.0的文档:
repartition[排序] coalesce :系统对每个输入进行分区(无序处理)(除非输入已分区)并对每个输入进行排序(除非已排序)。输入通过已排序输入的流式 coalesce 进行 join。如果一个或两个输入都已排序,则此策略是好的。
所以在我的例子中,评级是排序的(我认为),而每个xlabels DataSet 没有排序,因此这是最有效的策略。这个有什么问题吗?有其他方法吗?