本文主要介绍在Presto中部分与Sort(order by)相关的RBO优化。
MergeLimitWithSort的作用主要将Limit + OrderBy 算子转化为TopN算子,如下图的执行计划所示:

MergeLimitWithSort的实现代码也非常简单,主要是将Limit+OrderBy的Node替换成TopN的Node即可。
MergeLimitOverProjectWithSort 的作用是将Limit-Project-Sort的算子转化成Project-TopN的算子的形式,如下所示:

MergeLimitOverProjectWithSort的代码实现过程主要通过将Project的Source替换成一个TopN Node,其中N为Limit的数量,排序列为Sort的排序列。
RemoveRedundantSort 主要作用是去除只有1条结果或者0 条结果的Sort。如下执行计划中,order by 1是order by就只会有一条结果,因此Sort算子可以裁剪掉。

其代码实现过程如下所示:
- public Result apply(SortNode node, Captures captures, Context context)
- {
- // 如果sort的source无结果的话,则将整个执行计划都裁掉
- if (isAtMost(node.getSource(), context.getLookup(), 0)) {
- return Result.ofPlanNode(new ValuesNode(node.getId(), node.getOutputSymbols(), ImmutableList.of()));
- }
- // 如果只有一条结果的话,直接裁掉Sort算子
- if (isScalar(node.getSource(), context.getLookup())) {
- return Result.ofPlanNode(node.getSource());
- }
- return Result.empty();
- }
PruneOrderByInAggregation 主要作用是裁剪掉聚合函数内部的sort算子。如下执行计划所示,sum(id order by id)中的order by无意义,因此可以裁剪掉。

其代码实现的过程如下所示:
- public Result apply(AggregationNode node, Captures captures, Context context)
- {
- ......
- for (Map.Entry<Symbol, Aggregation> entry : node.getAggregations().entrySet()) {
- Aggregation aggregation = entry.getValue();
- // 聚合操作中无sort操作,不做处理
- if (!aggregation.getOrderingScheme().isPresent()) {
- aggregations.put(entry);
- }
- // getAggregateFunctionImplementation can be expensive, so check it last.
- else if (metadata.getFunctionAndTypeManager().getAggregateFunctionImplementation(aggregation.getFunctionHandle()).isOrderSensitive()) {
- aggregations.put(entry);
- }
- // 聚合操作中无sort操作,裁剪掉sort算子
- else {
- anyRewritten = true;
- aggregations.put(entry.getKey(), new Aggregation(
- aggregation.getFunctionCall(),
- aggregation.getArguments(),
- aggregation.isDistinct(),
- aggregation.getFilter(),
- Optional.empty(), // 裁剪sort算子的地方
- aggregation.getMask()));
- }
- }
- ......
- }