分布式 | Left join ... on shardingColumn = N 优化为整体下发单节点的可行性

作者:文韵涵

爱可生 DBLE 团队开发成员,主要负责 DBLE 需求开发,故障排查和社区问题解答。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


背景

SQL-1:select a.name from tabler a Left Join gtable1 b on a.name = b.name and a.id = 2; (tabler、gtable1分别为分片表、全局表,其中tabler.id 为分片列;两个表配置的节点均为dn1~4)

查看 SQL-1 在 DBLE 中执行计划 Explain-1:

从explain中,将分片表 tabler 分别下发各个节点,全局表 gtable1 单独下发一个节点分别获取数据;

另外,没有 ”on a.name = b.name and a.id = 2 ” 条件的身影,想必是在DBLE层面对数据进行的join合并和筛选处理了。

提出Suppose-1

SQL-1 on中 “a.id = 2”,a.id作为分片列; 看起来可以根据a.id明确路由单节点下发tabler表,然后gtable1作为全局表可以随意选一个路由节点下发;

具体假设:根据“a.id = 2” 确定路由节点为dn1,那么SQL-1貌似可以整体下发(直接透传)到dn1节点中了,这样以来可以减少在DBLE层面join数据的处理。

After a while:....咦....啊...为啥....好像不行诶...........

经过一顿胡乱操作,发现 Suppose-1 的优化方案并不适合在left/right join场景下。

SQL-2:select a.name from tabler a Left Join gtable1 b on a.name = b.name where a.id = 2;

提出的Suppose-1 的实现方案几乎与在DBLE中处理SQL-2的思维雷同;

反思:误认为 SQL-2中 “where a.id = 2” 与 SQL-1中 “on ... a.id = 2 ”属于同一种过滤。

正视On和 Where的定义

  • On:作为两表在做笛卡尔积关联时,附加的关联条件,生成虚拟表V。
  • Where:对虚拟表V(两表关联后的结果)筛选时用的过滤条件,只保留符合条件的数据行

Mysql中执行 Left Join

1、Employee 为左表,Info 为右表,On关联条件:a.name = b.name

Result-1:左表数据全部展示,右表符合关联条件的则显示对应的信息,若没有关联信息,则右表填充null。(图中,左表的全部信息有10个name,而右表的name没有George,Tom,Tony,所以对应右表显示null)

2、在Result-1中追加 On 关联条件:b.country = 'China' 。

Result-2:左表数据依旧全部展示,在Result-1基础上的数据行找到符合 “b.country = 'China' ” 关联条件,如果不符合,则右表填充null。(图中,右表中只有两条country为China的数据,其余的都不符合关联条件,所以右表显示null)

3、在Result-1中追加 Where 过滤条件:b.country = 'China' 。

Result-3:在Result-1的基础上,进行 “b.country = 'China' ” 过滤条件的筛选,剔除不符合的数据行。(图中,只显示符合country为China过滤条件的两条数据)

总结

  • 从上面的 Result-2 和Result-3 ,可以很明显的看出Left join下使用 On 和Where 的区别:

    • On :关联条件不影响左表全部信息显示,它是作为右表是否符关联条件,不符合的,右边将由NULL填充。
    • Where :不关心JOIN类型,在虚拟表V基础上再进行条件过滤,只返回符合条件的数据行。
  • LEFT JOIN

    • 水平视角,等价于 左表的全部信息 +(右边符合关联条件的信息+不符合关联条件的NULL填充)
    • 垂直视角,等价于 INNER JOIN + 补足左表 + 右表NULL填充
    • 左外连接 (⟕) :左外连接写成R ⟕ S,其中R与S为关系。左外连接的结果包含R中所有元组,对每个元组,若在S中有在公共属性名字上相等的元组,则正常连接,若在S中没有在公共属性名字上相等的元组,则依旧保留此元组,并将对应其他列设为NULL。

  • 在LEFT JOIN中,左表的数据需全部显示;根据提出的Suppose-1方案, SQL-1中只会下发dn1一个节点,并不符合on关联条件的定义,所以Suppose-1优化方案不可行;(目前的Explain-1是符合预期的)

(Right Join与 Left Join相似,Right Join的左边作为右表,右边作为左表,可套用以上的描述,然后在显示的两表调换顺序即可)。

MySQL Left Join 中 on 关联条件的实现逻辑

数据准备

create table A(c1 int, c2 int); create table B(c3 int, c4 int);

insert into A values(1,1),(22,22),(333,333);   insert into B values(0,1),(1,1);

查询

图1如下:

图2如下:

提问

图1结果符合预期,但图2的结果有点不理解,不是说 on 条件不会过滤么,这里好像过滤了吧?

解答

图2中没有对数据过滤; 需要了解 MySQL 中采用嵌套循环连接的join算法,这里列举 Left join实现的伪代码:

for(leftTable :leftRow) {// 遍历左表的每一行
  boolean b = false;
  for(rightTable: rightRow) {// 遍历右表每一行
    if(满足on关联条件){
        System.out.println(leftRow + rightTable); // 则左、右行进行合并输出
        b=true;
    }
  }
  if(!b) { // 遍历完rightTable,发现leftRow没有关联对应的行,则用null补一行
    System.out.println(leftRow + NULL); // 则左行与NULL合并输出
  }
}

具体解读:

图1,“A.c1 > 0” 作为关联条件总是为true,查询结果等于两个表的笛卡尔积。

图2,“A.c1 = 333” 也还是关联,套用伪代码:左表c1列为333的时候,已经满足了on条件,左、右边数据合并;左表c1列为1和22时,不符合关联条件,所以各自就用左边数据+NULL合并补了一行;

参考文档


MySQL分布式中间件DBLE
DBLE是一个基于MySQL的高可扩展性的分布式中间件,适用于高并发及TB级海量数据处理场景。

中国领先的企业数据处理技术整体解决方案提供商,开源数据库领域优秀企业。为大型行业用户的特定场景提...

371 声望
180 粉丝
0 条评论
推荐阅读
故障分析 | 一个因 SSL 配置导致的复制异常报错
在构建 MySQL 复制过程中,IO 线程始终连接不上主库,反复确认复制账号的权限、账号密码都没问题,最终定位为 SSL 配置的问题。作者:木板。某全国性股份制银行 DBA。擅长 DB2,MySQL 和 Oracle 数据库的运行维护...

爱可生云数据库

Django笔记二十八之数据库查询优化汇总
这一篇笔记将从以下几个方面来介绍 Django 在查询过程中的一些优化操作,有一些是介绍如何获取 Django 查询转化的 sql 语句,有一些是理解 QuerySet 是如何获取数据的。

Hunter阅读 599

封面图
分而治之--浅谈分库分表及实践之路 | 京东云技术团队
之前总在聊微服务, 微服务本身也是分布式系统,其实微服务的核心思想是分而治之,把一个复杂的单体系统,按照业务的交付,分成不同的自服务,以降低资深复杂度,同时可以提升系统的扩展性。

京东云开发者1阅读 270

封面图
分库分表的 21 条法则,hold 住!
不着急实战,咱们先介绍下在分库分表架构实施过程中,会接触到的一些通用概念,了解这些概念能够帮助理解市面上其他的分库分表工具,尽管它们的实现方法可能存在差异,但整体思路基本一致。因此,在开始实际操作...

Java架构师阅读 171

数据分片-库内分表实践
由于疫情不再进行防控,项目的基本业务是扫码乘坐公交车,订单表的增量相比过去有了较大的增加, 目前系统中存在订单表保存3个月的数据,数据在1300W左右,按现在日增数据为30W,月增量为900W 那么未来某个时刻的...

Ekko阅读 163

中国领先的企业数据处理技术整体解决方案提供商,开源数据库领域优秀企业。为大型行业用户的特定场景提...

371 声望
180 粉丝
宣传栏