作为分库分表中间件,分片条件应用分区剪裁规则,减少扫描范围是必须做的优化.
在方案1中,使用了一次下推,一次关系表达式重写,一次上拉,在然后生成分片执行的SQL,然后使用CBO生成执行器.
在生成SQL的代码里,仅仅是使用分片信息作为区分在中间件中运算的部分与在存储数据库中运行的部分是不足够的.
我们还要考虑以下因素,生成的SQL能否在数据库中运行,关系表达式以及他们的组合是否能变成SQL,生成的SQL在数据库中执行高效.所以我们需要进一步定制规则来优化.
新的关系表达式重写器
我们不妨制作一个关系表达式来表达下推的SQL,值得注意的是,该操作是在关系表达式重写阶段进行的,下面描述的LogicalTable指的是逻辑表.
BottomView extends TableScan{
select;
from;
where;
joinGlobalTable{
equalKeys
};
sort;
limit;
}
这个关系表达式实际上就是
select … from … where … order … limit …
生成模板,特别地,针对分库分表中间件的全局表join优化,我们可以在from处嵌入一个全局表或者ER表来实现join的下推.
然后我们可以分析该SQL实际上对应的是什么关系表达式
LogicalTableScan
LogicalFilter
LogicalTableScan
LogicalProject
LogicalFilter
LogicalTableScan
LogicalSort
LogicalProject
LogicalFilter
LogicalTableScan
LogicalSort
LogicalProject
LogicalFilter
LogicalJoin
LogicalTableScan
LogicalTableScan
…..
在关系表达式重写阶段,对上述的模式进行匹配,并使用新的BottomView 替代原表达式.
特别地,针对limit a,b 我们需要进行简单的重写为limit 0,a+b,来确保扫描的数据范围在语义之内.
如果我们完成了这个关系表达式重写器,后续的UnionAll上拉实际上可有可无的,BottomView可以自己具备UnionAll多个分片SQL的语义,也可以显式在它之上加入UnionAll显式说明它就是包含多个输入的语义.
因为BottomView 是自己实现的关系表达式,所以我们需要自己实现特定的执行器生成接口,也可以使用一些工具或者规则把它还原成LogcalTable然后使用Calcite内置的执行器.
执行阶段
在执行阶段,我们可以分析BottomView中的where条件,得出分片范围,然后根据BottomView的属性生成各个分片的sql,然后顺利执行
思考
如果多个SQL中仅仅where条件是不同的,怎样使它们共用一个执行器而仅仅在生成SQL的时候使用不同的where对象生成不同分片的SQL.