一. InlineProjections优化规则
1. 优化效果
InlineProjections 用来优化常量表达式的数据列,此优化规则会将常量表达式的数据列直接裁剪掉,引用到常量表达式数据列的输出改写成直接使用常量计算。这样可以减少数据列传输和计算。
如下图是个优化效果示例:
2. 实现原理
public Result apply(ProjectNode parent, Captures captures, Context context)
{
ProjectNode child = captures.get(CHILD);
// taget是需要优化掉的child Project的常量数据列,如上图的红框中的列
Sets.SetView<Symbol> targets = extractInliningTargets(parent, child);
if (targets.isEmpty()) {
return Result.empty();
}
// inline the expressions
Assignments assignments = child.getAssignments().filter(targets::contains);
//parentAssignments为parent中引用到project source常量数据式的列,如上图的绿框中的列
// 如下的作用是绿框的引用到常量列的输出换成常量
Map<Symbol, Expression> parentAssignments = parent.getAssignments()
.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> inlineReferences(entry.getValue(), assignments)));
// Synthesize identity assignments for the inputs of expressions that were inlined
// to place in the child projection.
// If all assignments end up becoming identity assignments, they'll get pruned by
// other rules
Set<Symbol> inputs = child.getAssignments()
.entrySet().stream()
.filter(entry -> targets.contains(entry.getKey()))
.map(Map.Entry::getValue)
.flatMap(entry -> SymbolsExtractor.extractAll(entry).stream())
.collect(toSet());
//裁剪掉project source的常量数据列
Assignments.Builder childAssignments = Assignments.builder();
for (Map.Entry<Symbol, Expression> assignment : child.getAssignments().entrySet()) {
if (!targets.contains(assignment.getKey())) {
childAssignments.put(assignment);
}
}
for (Symbol input : inputs) {
childAssignments.putIdentity(input);
}
return Result.ofPlanNode(
new ProjectNode(
parent.getId(),
new ProjectNode(
child.getId(),
child.getSource(),
childAssignments.build()),
Assignments.copyOf(parentAssignments)));
}
二. RemoveRedundantIdentityProjections优化规则
1. 优化效果
RemoveRedundantIdentityProjections较为简单,用于去除输入和输出是一模一样的算子。
2. 实现原理
private static boolean outputsSameAsSource(ProjectNode node)
{
return ImmutableSet.copyOf(node.getOutputSymbols()).equals(ImmutableSet.copyOf(node.getSource().getOutputSymbols()));
}
@Override
public Pattern<ProjectNode> getPattern()
{
return PATTERN;
}
@Override
public Result apply(ProjectNode project, Captures captures, Context context)
{
//上边的outputsSameAsSource判断此算子的输出和source的输出是否是一模一样的,如果是一模一样的话,此算子是毫无作用的,直接用此算子的Source的输入替换此算子的输出即可
return Result.ofPlanNode(project.getSource());
}