首先我们要展示一下 Global 表的能力,也就是 Global 表怎么样在四个节点上工作。我们现在看一下 Global 表,应该是预先写好了两条数据。现在我新增一条数据上去,看怎么样在这四张表当中去维护。这是一条 insert 数据,id 我们指定为1024,可以查到。然后我们去真正的数据库节点上,端口 33061 和 33062。我们刚才已经看到 dn1 到 dn4。对于 33061 这个实例来说就是 db_1 和 db_3。我们去看接下来数据状态,我们可以看到 tb_global_2 里面已经有这条数据了。我们换一下从 db_3 当中去查一次也是三条数据。我们换一下,从 33062 端口里面去演示一下其实 DBLE 内部是通过两阶段提交的分布式事务来做到。四个节点数据保持一致的 Global 表基本构成就是这样的。所以我们现在回到 8066 端口来做一下 tb_mod 表和 Global 表的 JOIN。
我们先讲一下 INNER JOIN,INNER JOIN 是比较简单的一种情况。我们直接和本地的数据库 JOIN 就可以。结果是正确的,因为现在只有两条数据。然后我们通过 EXPLAIN 看一下,是不是跟普通 JOIN 步骤一样。我把所有数据收集到中间件节点再做 JOIN,结果应该有六行。其实前四个 SQL 内容都是一样的,只不过被路由到了不同的节点。整个 JOIN 被直接下发下去,然后在中间件简单合并一下就结束了。
我们再看 LEFT JOIN,拆分表 LEFT JOIN Global 表是可以的。RIGHT JOIN其实是 LEFT JOIN 反过来,相当于 Global 表作为左表的 LEFT JOIN 拆分表。这时候我们可以发现查询结果已经不一样了。已经回到我们讲过的的跨库 JOIN,这样一个执行的方式,是把所有表的数据都收集起来。然后在中间件去做 JOIN,而不是语句直接下发。
大家可以想象一下为啥 RIGHT JOIN 不行?
其实这涉及到了 MySQL 语义,如果我整体的去把 JOIN 下发的话,因为我的 RIGHT JOIN 需要筛选出 Global 表有的拆分表没有的。如果我直接下发的话 RIGHT JOIN,每个分片都会丢一部分这类型的数据。
虽然 Global 表和拆分表的 INNER JOIN 可以优化,但是 LEFT JOIN 还是会回到跨库查询,所以大家业务需要严格审核 SQL,避免带来性能问题。
好,我们今天先介绍到这里。
图文稿为了方便阅读,在不影响学习的情况下优化了一些口语化词汇,文稿与视频会尽量保持一致。