calcite提供了两种查询优化器:
- 基于规则的启发式优化器HepPlanner(rule-based optimizer RBO)
- 基于代价的VolcanoPlanner(cost-based optimizer CBO)
本篇介绍HepPlanner的工作原理。在HepPlannerTest.java中添加如下代码进行源码分析:
// HepPlannerTest.java
@Test public void testHepPlanner() {
HepProgramBuilder programBuilder = HepProgram.builder();
// 添加join中谓词下推的rule
programBuilder.addRuleInstance(FilterJoinRule.FilterIntoJoinRule.FILTER_ON_JOIN);
HepPlanner planner = new HepPlanner(programBuilder.build());
planner.setRoot(tester.convertSqlToRel("SElECT NAME FROM EMP e JOIN DEPT d ON e.DEPTNO = d.DEPTNO WHERE COMM > 1").rel);
RelNode newRelRoot = planner.findBestExp();
newRelRoot.toString();
}
setRoot
首先需要设置planner root
// HepPlanner.java
public void setRoot(RelNode rel) {
root = addRelToGraph(rel);
dumpGraph();
}
// 递归将rel tree中的relnode转化成hepRelVetex, 构造dag
private HepRelVertex addRelToGraph(
RelNode rel) {
// Check if a transformation already produced a reference
// to an existing vertex.
if (graph.vertexSet().contains(rel)) {
return (HepRelVertex) rel;
}
// Recursively add children, replacing this rel's inputs
// with corresponding child vertices.
final List<RelNode> inputs = rel.getInputs();
final List<RelNode> newInputs = new ArrayList<>();
for (RelNode input1 : inputs) {
HepRelVertex childVertex = addRelToGraph(input1);
newInputs.add(childVertex);
}
// 当有节点修改,调用onCopyHook进行通知
if