禁止 Mysql 三表 Join 的原因
大约 11 分钟
禁止 Mysql 三表 Join 的原因
在阿里巴巴开发规约中,明确禁止MySQL进行三表的Join关联。这一规定作为强制规范,要求每一个程序员必须遵守。
本文将结合自身理解,详细说明这一规定的原因及其解决方案。
禁用多表关联的原因分析
产品的强制要求
- 阿里巴巴的数据库设计:
- 阿里巴巴对原始的 MySQL 进行了大量改造,底层数据库使用的是经过 MySQL 升级改造而来的 OceanBase (分布式数据库,淘宝在用)。
- OceanBase只允许进行两表关联,这是其产品设计的强制要求。
- 中间件 MyCAT:MyCAT是一个分库分表的中间件,它也只支持两表关联,>= 三表就不支持了。
MySQL自身的设计缺陷
SQL优化器的问题:
- MySQL的SQL优化器对多表关联优化做得不够好,很多时候执行计划与预期不符。
嵌套查询的性能问题:
- 多表关联时,MySQL通常采用嵌套循环关联(NLJ),类似于三层循环。
- 小表驱动大表是 NLJ 的核心实现,但在选择小表时需要大量的CPU 运算和动态分布分析。
- 多表嵌套查询时,MySQL 的性能较差,因此不推荐使用三表以上的关联。
2.3 数据迁移和改造的困难
- 依赖数据源的特性获取数据:
- 数据迁移时,跨库直接访问会变得困难。
- 例如,商品库和订单库物理上隔绝后,不能通过一条SQL语句完成两表关联,必须通过代码进行数据交互。
- 水平分表的复杂性:
- 当订单明细表变得超大时,需要进行水平分表。
- 水平分表后,单条 SQL 语句无法处理所有分片的数据,必须对所有分片遍历,增加了复杂性。
多表关联的解决方案
临时性解决方案
分散查询:
- 将三表查询拆分为多个单表查询。
- 例如,先查询A表的ID,再用这些ID查询B表,最后用B表的ID查询C表。
局限性:
- 只适用于数据量小和内关联(inner join)的情况。
- 如果A表查询到三万个ID,代入IN条件执行效率会很低,且超过SQL上限。
- 不适用于左关联(left join)的情况。
反范式表 / 冗余表
- 概念:
- 将原始数据存储按正常方式进行,但在数据变更时,触发代码将数据写入反范式表。
- 反范式表是通过数据冗余方式组织成的大表,用于查询时不再面向底层小表。
- 优点:
- 提高查询效率,避免多表关联带来的性能问题。
- 适用于数据量较小的项目。
- 特别适合单库处理
::: 为什么不用视图?
视图只是逻辑上的数据处理,底层仍需多表查询,无法解决性能问题。
:::
数据仓库及数据集市
概念:
- 数据仓库和数据集市通过ETL(数据导出、加工和导入)过程,对数据进行加工。
- 生成报表、中间表和数据视图等,提供更高效的数据查询。
日中处理:
- 每天对数据进行抽取和加工,生成数据集市。
- 数据集市通过 T+1(数据延迟一天)的方式实现。
倒排表:
- 通过倒排表(倒排索引)解决分片查询问题。
- 例如,通过订单ID对订单明细表分片,实现高效查询。
结论
阿里巴巴禁止MySQL进行三表关联的原因主要包括产品设计要求、MySQL自身设计缺陷和数据迁移改造的困难。
为解决多表关联问题,可以采用临时性解决方案、反范式表和数据仓库及数据集市等方法。这些方法各有优缺点,需根据具体应用场景进行选择。