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_FIRSTBROADCAST_HASH_SECOND

joinWithHugejoinWithTiny

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());
}