分布式 | Global 表 Left Join 拆分表实现原因探究
本文关键字:JOIN、原理解析、分库分表
问题
前几天,社区交流群一个小伙伴提出这样一个问题:
小伙伴说:全局表和分片表的左连接能否支持 -- 目前测试 mycat 结果不对。
很显然是想要脱坑的 mycat 用户,急需找个替代品,主要的是他也找到了,哈哈哈。
场景重现
首先我们创建一个全局表和一个拆分表,各自设置两个分片节点,全局表在两个节点数据一致,拆分表 id=1、2 的在一个节点,id=5000001 的在另一个节点,其中 id=1 和 id=2 的只有 id 字段值不同、code&content 字段值都一样。
mycat 场景重现
以上准备工作完成,接下来我们通过 a.id、b.code 将两张表左连接查询,结果如小伙伴所言:mycat 结果不对。
dble 场景重现
以上准备工作完成,接下来我们通过 a.id、b.code 将两张表左连接查询,结果如下所示;显而易见实际得到的结果符合预期想要的结果。
结果探究
根据以上使用 mycat 和 dble 进行 global left join 拆分表查询得到不同的结果,我们尝试着使用 explain 查看同一种类型的查询在执行计划上会有什么不同?
mycat 执行计划
根据上图执行计划,我们简单分析一下。
mycat 会将 sql 原封不动的交由分片配置的所有实例去执行,然后根据执行结果进行合并,这里合并只是简单的对结果进行累加,很显然这样的计划显示 mycat 内部处理逻辑是错误的。因为全局表在每个配置的节点都会存储相同的数据,如果将每个节点和拆分表 left join 的结果进行简单的 union all 合并,会造成数据的重复,不能保证数据的准确性。有些小伙伴可能猜想 union 不是会保证数据不重复吗?如果用 union 是否可行?同样分析一下。
上述结果仍然得不到我们想要的结果,因为 union 只是解决数据重复的问题,不适用于因为分片而导致的数据重复问题;试想一下,如果 DBLE 未来通过某种算法可以对各个节点的结果集做一个准确的合并,那么这样的问题也就迎刃而解,也会性能方面有个整体的提升。
实际上我们想象中的 X 算法还没有一个良好的实现和证明,但现在又要解决查询正确性的问题,那么 dble 是怎么做的呢?下面我们来看下 dble 的执行计划:
从上面执行计划来看,简单分析下流程:
dble 内部对于这种查询作出了一些区分:全局表只会下发一个实例,拆分表都会下发,然后针对结果做合并,这种处理逻辑肯定是没有错误的,只不过执行计划看起来相对复杂一些,这也代表在 dble 内部实现层面上下了不少功夫,但是这也是为了保证数据准确性而作出的一些牺牲吧。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341