基于Calcite制作分库分表中间件(方案3)

基于Calcite制作分库分表中间件(方案3)

上次提到模版结合新自定义关系表达式来实现有效的sql生成,那么我们可不可以像方案1中借鉴Calcite现成的功能来实现对之前的方案进行改进.

答案是有的

直观的改进方法有三种

 

目录

基于Calcite制作分库分表中间件(方案3)

表函数法

规则下推+自定义关系表达式

自定义关系表达式+自定义生成执行器实现


表函数法

org.apache.calcite.rel.core.TableFunctionScan

实际上分库分表的逻辑表可以表述为

形式1:分片函数_表名(单分片值),分片函数_表名(范围分片值)

形式2:分片函数(表名,分片值),分片函数(表名,范围分片值)

分片函数=分片键(拆分键)+算法

而分片分表的谓词分析就是为了提取分片值

逻辑表本身就自带了分片函数信息

所以,直接提取分片值.对逻辑表的分片函数进行赋值,就可以得到对应的物理表范围.

select * from table where id = 1;//table是逻辑表
=>
select * from table(1) where id = 1;
=>
select * from table_0 where id = 1;//table_0是物理表

其中table带有了分片算法的信息,这样就完成了分区剪裁

 

在使用TableFunctionScan的情况下,可以参考的下推规则是

org.apache.calcite.rel.rules.FilterTableFunctionTransposeRule

View的设计与它是相同,把更多操作放到TableFunctionScan下面,即叶子节点以下.

TableFunctionScan
    Filter
        RelNode

该方案可以很方便生成以下模板,也可以在生成RelNode,SQLNode的时候把逻辑表名字替换为TableFunctionScan,达到相同效果.

select * from table where condition
=>
select * from table_0 where condition
select * from table_1 where condition
select * from table_2 where condition

也支持使用表函数直接给与分片范围

select * from tableFunction(range,1,10)

当分片函数相同的时候,可以认为它们的物理表的存储分布是相同的,物理表名生成规则也是相同的,在涉及多个相同分片函数的逻辑表带等价关联操作,可以直接把他们的运算下放到存储节点运算.往后的教程我会更详细介绍这个技术.

 

本质上表函数能做的事情很多,它可以返回结果集,类似支持赋参的View(但不是返回View)

 

规则下推+自定义关系表达式

org.apache.calcite.interpreter.Bindables.BindableTableScan

BindableTableScan也是一种View,它演示了Project,Filter的下推,是Bindalbe执行器家族的稍微特殊的物理关系表达式

Project
    Filter
------------------------------------
Project
        TableScan
------------------------------------
TableScan

它本质上也是一种穷举所有关系表达式形态的策略来实现匹配,然后使用枚举所有可以合拼多个关系表达式的特殊节点替换原关系表达式,然后应用规则,然后通过定义的代码完成SQL生成或者执行.

 

自定义关系表达式+自定义生成执行器实现

org.apache.calcite.adapter.jdbc.JdbcImplementor

 

public class JdbcImplementor extends RelToSqlConverter {
  public JdbcImplementor(SqlDialect dialect, JavaTypeFactory typeFactory) {
    super(dialect);
    Util.discard(typeFactory);
  }

  // CHECKSTYLE: IGNORE 1
  /** @see #dispatch */
  public Result visit(JdbcTableScan scan) {
    return result(scan.jdbcTable.tableName(),
        ImmutableList.of(Clause.FROM), scan, null);
  }

  public Result implement(RelNode node) {
    return dispatch(node);
  }
}

在RelToSqlConverter 帮助下我们可以完成对RelNode生成SQL,在特定的遍历顺序下,我们通过重写阶段生成函数,结合自定义的关系表达式,完成SQL的准确生成.这阶段实际上是在生成执行器的时候进行的.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值