author:chenjunwen
qq:294712221
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

单表与单表

只涉及单表与单表之间的join,只要它们的存储节点相同,就可以下推

任意表与全局表

涉及任意表与全局表之间的left/inner join都可以下推

相同数据分布关系(ER关系)

涉及分片表之间的分片算法的数据分布相同同时使用拆分键进行等值查询就可以下推
分片算法的数据分布相同即除了字段信息外,其他分片算法配置相同
值得注意的是,上述说的表并非指

a join b on a.id = b.id

中a与b只能是逻辑表,而是可以使用多次运算得出的临时表

FULL JOIN都不支持下推.Mysql没有这个运算,不讨论FULL JOIN

所有
是指
INNER,LEFT,RIGHT,SEMI,ANTI

任何表与虚拟表(一般是mysql的系统元数据表)都不能下推

但把虚拟表配置成单表,全局表,分片表是可以的

a join b on a.id = b.id join c on a.id =c.id

在mycat眼里是这样的
(a join b on a.id = b.id) join c on a.id =c.id

整体运算符结合律

如果a是分片表 join b全局表 那么(a join b on a.id = b.id)也视为分片表
如果a是全局表 join b单表 那么(a join b on a.id = b.id)也视为单表
如果a是分片表 join b单表 那么(a join b on a.id = b.id)也视为分片表

以上结合律不区分左右表

下面是在此框架下的具体规则

基于表类型的下推规则

左表 右表 JOIN类型 必要下推条件
单表 单表 所有 targetName相同
单表 全局表 所有
单表 分片表 同全局表与分片表,即INNER,RIGHT targetName相同
全局表 单表 所有
全局表 分片表 INNER,RIGHT push_down_join_broadcast可以强制下推
全局表 全局表 所有
分片表 全局表 INNER,LEFT,SEMI,ANTI(不支持RIGHT) push_down_join_broadcast可以强制下推
分片表 单表 同分片表与全局表 targetName相同
分片表 分片表 所有 ER关系而且分片键等值查询

单表与分片表/分片表与分片表 在targetName相同的时候,单表升级为全局表(v1.21实现,此前不能)

基于分区键与分片表的下推规则(1.21-2021-11-6)

(v1.21实现,此前不能)

分区键是能对应一个分区的字段
分片键是对数据进行分区的字段,它对应一个或者多个分区

当拆分键,分片键只有一个的时候,它就是分区键
当拆分键有多个的时候,根据情况而定,比如分库键就不是分区键

分片算法中的映射算法

分片算法描述了数据如何映射到数据库实例与分区的算法
其中用targetName代表数据库实例,所以targetName是相同的时候,它们的数据就在相同的数据库实例上.

当join中带有分区键的等值查询的时候,而且左表是分片表,而且该分区键带有等值查询,命中一个分区(点查),
此时左表与右表都分别命中一个分区,则触发基于分区键的分片表下推规则
该规则不区分左右表

分片表 全局表 所有
分片表 单表 所有 targetname相同,
左侧分片表是单实例分表(单库分表)
(实质上是单表升级为全局表)
分片表 分片表 所有 右侧分片表是多实例单表(分库)
两表分片算法中的targetName映射算法相同
但允许表名映射算法不同
两表targetName集合相同
(由分片算法决定,内置自动hash型实现)

两表分片算法中的targetName映射算法相同
但允许表名映射算法不同

在自动hash型算法的语境下
比如分库数量相同,分表数量不相同,右表的分表数量是1,这个就满足
两表分片算法中的targetName映射算法相同
两表targetName集合相同
但是它们表名映射算法不同
但是要求右侧分片表是多实例单表(分库),所以右表的分表数量只能是1

实际上ER表也属于两表分片算法中的targetName映射算法相同

更为广泛的分片表规则,此规则一般使用 基于位置的下推规则 实现

左表右表都进行基于分区键的点查,都分别命中一个分区

分片表 分片表 所有 targetname相同
两表分片算法中的targetName映射算法相同
两表targetName集合相同
(由分片算法决定,内置自动hash型实现)
使用参数动态计算出对应的左右分区并进行join

基于位置的下推规则

(v1.20开始实现逐渐完善,v1.21完善整个规则)
在SQL带有完整参数(相对于参数化)的时候,如果计算得出左表与右表分别只有一个分区,而这两个分区的targetName是相同的,则把SQL中的左表与右表的逻辑库逻辑表名替换为对应的物理库物理表名.

此规则支持所有join类型
此规则是 基于分区键与分片表的下推规则 的扩展, 基于位置的下推规则 不支持参数化,而前者支持.
左表右表都进行基于分区键的点查,都分别命中一个分区
该规则不区分左右表

分片表 全局表 所有
分片表 单表 所有 targetname相同
左侧分片表无要求
分片表 分片表 所有 targetname相同
左右侧分片表无算法要求
左右两表谓词命中一个分区

注意

左表右表会被join reorder,进行交换左右位置,一般交换的join类型是inner join,此时实际上不区分左右表
以上规则适用于能被重写为全局索引表的分片表
以上规则适用于能被重写为join的子查询,无法下推的join运算,mycat会进行运算得出正确的结果
Mycat2具有把left join和right join的关系表达式重写为inner join的能力,上述的left join,right join仍然有可能使用inner join的规则优化,具体执行计划请使用explain语句查看