Flint Join优化之Hint(优化器)
Flink目前主要有3种join :
- join :inner join,等值连接
- outerJoin :外连接,分为left-outer join(左连接)、right-outer join(右连接)、full-outer join(全外连接)
- cross : 笛卡尔积
Flink提供了优化器“hint”(提示)以告诉join函数优化器选择一些执行策略。
JoinHint
枚举 | 介绍 | 适用场景 |
OPTIMIZER_CHOOSES | 将选择权交予Flink优化器 / 默认 | |
BROADCAST_HASH_FIRST | 广播第一个输入端,同时基于它构建一个哈希表 | 第一个输入端规模较小 |
BROADCAST_HASH_SECOND | 广播第二个输入端并基于它构建哈希表 | 第一个输入端规模较小 |
REPARTITION_HASH_FIRST | 该策略会导致两个输入端都会被重分区,但会基于第一个输入端构建哈希表 | 第一个输入端数据量小于第二个输入端的数据量,但两个输入段规模都很大,并且没有已存在的分区以及排序顺序可被使用 |
REPARTITION_HASH_SECOND | 该策略会导致两个输入端都会被重分区,但会基于第二个输入端构建哈希表 | 第一个输入端数据量大于第二个输入端的数据量,但两个输入段规模都很大,并且没有已存在的分区以及排序顺序可被使用 |
REPARTITION_SORT_MERGE | 输入端被以流的形式进行连接并合并成排过序的输入 | 适用于一个或两个输入端都已排过序的情况; |
使用方式
ds1.join(ds2, JoinHint.BROADCAST_HASH_FIRST);
ds1.leftOuterJoin(ds2, JoinHint.BROADCAST_HASH_FIRST);
ds1.rightOuterJoin(ds2, JoinHint.BROADCAST_HASH_FIRST);
ds1.fullOuterJoin(ds2, JoinHint.BROADCAST_HASH_FIRST);
另外flink还提供了两个函数来调用 BROADCAST_HASH_FIRST 和 BROADCAST_HASH_SECOND :
joinWithHuge、joinWithTiny
public <R> JoinOperatorSets<T, R> joinWithHuge(DataSet<R> other) {
return new JoinOperatorSets<>(this, other, JoinHint.BROADCAST_HASH_FIRST);
}
public <R> JoinOperatorSets<T, R> joinWithTiny(DataSet<R> other) {
return new JoinOperatorSets<>(this, other, JoinHint.BROADCAST_HASH_SECOND);
}
由于JoinHint只适用于Json函数,如果使用cross来产生笛卡尔积则需要使用另外的优化器。
CrossHint有3个枚举 :
枚举 | 介绍 |
OPTIMIZER_CHOOSES | 将选择权交予Flink优化器 |
FIRST_IS_SMALL | 第一个输入端小于第二个输入端; |
SECOND_IS_SMALL | 第二个输入端数据量小于第一个输入端 |
cross并没有像join一样给用户提供不同的枚举传参来选择不同的优化器,而是把不同的优化器写到不同的方法里面,下面3个方法本质是一样的,都是产生笛卡尔积,只是优化器不一样。
- cross : OPTIMIZER_CHOOSES
- crossWithHuge : FIRST_IS_SMALL
- crossWithTiny : SECOND_IS_SMALL
public <R> CrossOperator.DefaultCross<T, R> cross(DataSet<R> other) {
return new CrossOperator.DefaultCross<>(this, other, CrossHint.OPTIMIZER_CHOOSES, Utils.getCallLocationName());
}
public <R> CrossOperator.DefaultCross<T, R> crossWithHuge(DataSet<R> other) {
return new CrossOperator.DefaultCross<>(this, other, CrossHint.FIRST_IS_SMALL, Utils.getCallLocationName());
}
public <R> CrossOperator.DefaultCross<T, R> crossWithTiny(DataSet<R> other) {
return new CrossOperator.DefaultCross<>(this, other, CrossHint.SECOND_IS_SMALL, Utils.getCallLocationName());
}