基于Calcite制作分库分表中间件(方案1)
分库分表中间件的查询引擎是特别重要的一个功能,在一些Java生态的数据库中,使用Calcite作为查询器,在这个系列,我将为大家介绍如何在分库分表中间件中使用Calcite.
我会描述流程,而不在乎细节.细节会在后面的系列补充.
RBO第一阶段-下推分片条件谓词
使用下推LogicalFilter的规则与
org.apache.calcite.rel.rules.FilterTableScanRule
org.apache.calcite.rel.rules.ProjectTableScanRule
规则把Filter下沉到LogicTableScan之上
FilterTableScanRule和ProjectTableScanRule会把LogicalTable转化成
org.apache.calcite.interpreter.Bindables.BindableTableScan
如果不使用BindableTableScan,自己编写规则应用下面描述的重写器完成替换物理表也可以
RBO 第二阶段-关系表达式重写
然后进入RBO使用自己编写的关系表达式重写器,
把
org.apache.calcite.interpreter.Bindables.BindableTableScan#filters
进行谓词条件分析,得出逻辑表对应的一个或者多个物理表,把不符合谓词条件的物理表去掉,然后使用LogicalUnion把多个物理表LogicalTableScan以及合拼成一个新的关系表达式替换BindableTableScan
结果类似
LogicalUnion(LogicalProject(LogicalFilter(LogicalTableScan))....)
RBO 第三阶段-上拉UnionAll
RBO第二阶段上拉UnionAll
该阶段是为了下推更多关系表达式比如count,limit,join到UnionAll之下
RBO第四阶段-生成分片执行SQL
生成分片执行的SQL
上面提到LogicalTableScan已经被替换成物理表,所以物理表是带有分片信息的,此时我们只需要检查那些有多个输入的非叶子关系表达式(因为叶子都是LogicalTableScan),他们的输入节点是否都是同一个分片,如果是,则记录下来,自向上求出靠近根部的关系表达式是哪些,然后它们转换为SQL即可,并且使用临时表结合其他接口
org.apache.calcite.schema.TransientTable
org.apache.calcite.schema.QueryableTable
org.apache.calcite.schema.FilterableTable
org.apache.calcite.schema.ScannableTable
org.apache.calcite.schema.ProjectableFilterableTable
构造临时表保存关系表达式(在执行器执行的时候变成SQL就可以)或者保存对应的SQL
生成执行器
直接使用解释器运行或者使用CBO生成执行器即可
org.apache.calcite.interpreter.InterpretableConvention//解释器
org.apache.calcite.adapter.enumerable.EnumerableConvention//代码生成器
调优
1.调整下推谓词的规则
2.调整上拉UnionAll的规则
3.调整生成SQL的规则
4.提供统计元数据给CBO优化
5.完善谓词分析算法
6.Gather算子替换UnionAll算子,并完成并行执行器
7.可以试试上拉UnionAll再下推谓词的方案