Apache Calcite VolcanoPlanner优化过程解析
VolcanoPlanner是calcite自带的基于代价的优化器。在优化过程中,会计算优化规则生成的等价关系表达式的计算代价,通过动态规划算法找出整个最优的执行计划。
以下分析基于calcite1.26.0版本源码
使用VolcanoPlanner
这里以一个单元测试为例子解释如何使用calcite的VolcanoPlanner。
@Test
void myTest() {
ConnectionSpec SCOTT = CalciteAssert.DatabaseInstance.HSQLDB.scott;
SchemaPlus rootSchema = Frameworks.createRootSchema(true);
Map<String, Object> map = new HashMap<>();
map.put("jdbcDriver", SCOTT.driver);
map.put("jdbcUser", SCOTT.username);
map.put("jdbcPassword", SCOTT.password);
map.put("jdbcUrl", SCOTT.url);
map.put("jdbcCatalog", SCOTT.catalog);
map.put("jdbcSchema", SCOTT.schema);
JdbcSchema schema = JdbcSchema.create(rootSchema, "JDBC_SCOTT", map);
rootSchema = rootSchema.add(" JDBC_SCOTT", schema);
FrameworkConfig config = Frameworks.newConfigBuilder()
.defaultSchema(rootSchema)
.parserConfig(SqlParser.Config.DEFAULT)
.programs(Programs.standard()).build();
RelBuilder relBuilder = RelBuilder.create(config);
RelNode relNode = relBuilder.scan("EMP")
.project(relBuilder.field("DEPTNO"), relBuilder.field("ENAME"))
.sort(relBuilder.field("DEPTNO")).build();
VolcanoPlanner planner = (VolcanoPlanner) relNode.getCluster().getPlanner();
//获取期望的RelTraiset,这里是将Convention.None替换成EnumerableConvention
RelTraitSet desired = relNode.getTraitSet().replace(EnumerableConvention.INSTANCE).simplify();
//设置根节点,会从根节点开始迭代将所有子节点也注册到planner中
planner.setRoot(planner.changeTraits(relNode, desired));
RelNode result = planner.