跳至主要內容

禁止 Mysql 三表 Join 的原因

Hirsuntech大约 11 分钟

禁止 Mysql 三表 Join 的原因

在阿里巴巴开发规约中,明确禁止MySQL进行三表的Join关联。这一规定作为强制规范,要求每一个程序员必须遵守。

1735290872091.png

本文将结合自身理解,详细说明这一规定的原因及其解决方案。

禁用多表关联的原因分析

1735290971781.png

产品的强制要求

  • 阿里巴巴的数据库设计
    • 阿里巴巴对原始的 MySQL 进行了大量改造,底层数据库使用的是经过 MySQL 升级改造而来的 OceanBase (分布式数据库,淘宝在用)。
    • OceanBase只允许进行两表关联,这是其产品设计的强制要求。
  • 中间件 MyCAT:MyCAT是一个分库分表的中间件,它也只支持两表关联,>= 三表就不支持了。

MySQL自身的设计缺陷

  • SQL优化器的问题

    • MySQL的SQL优化器对多表关联优化做得不够好,很多时候执行计划与预期不符。
  • 嵌套查询的性能问题

    • 多表关联时,MySQL通常采用嵌套循环关联(NLJ),类似于三层循环。
    • 小表驱动大表是 NLJ 的核心实现,但在选择小表时需要大量的CPU 运算和动态分布分析。
    • 多表嵌套查询时,MySQL 的性能较差,因此不推荐使用三表以上的关联。
1735291092378.png

2.3 数据迁移和改造的困难

  • 依赖数据源的特性获取数据
    • 数据迁移时,跨库直接访问会变得困难。
    • 例如,商品库和订单库物理上隔绝后,不能通过一条SQL语句完成两表关联,必须通过代码进行数据交互。
  • 水平分表的复杂性
    • 当订单明细表变得超大时,需要进行水平分表。
    • 水平分表后,单条 SQL 语句无法处理所有分片的数据,必须对所有分片遍历,增加了复杂性。
1735291402290.png

多表关联的解决方案

临时性解决方案

分散查询

1735291505356.png
  • 将三表查询拆分为多个单表查询。
  • 例如,先查询A表的ID,再用这些ID查询B表,最后用B表的ID查询C表。

局限性

  • 只适用于数据量小和内关联(inner join)的情况。
  • 如果A表查询到三万个ID,代入IN条件执行效率会很低,且超过SQL上限。
  • 不适用于左关联(left join)的情况。

反范式表 / 冗余表

1735291601770.png
1735291601770.png
  • 概念
    • 将原始数据存储按正常方式进行,但在数据变更时,触发代码将数据写入反范式表。
    • 反范式表是通过数据冗余方式组织成的大表,用于查询时不再面向底层小表。
  • 优点
    • 提高查询效率,避免多表关联带来的性能问题。
    • 适用于数据量较小的项目。
    • 特别适合单库处理

::: 为什么不用视图?

视图只是逻辑上的数据处理,底层仍需多表查询,无法解决性能问题。

:::

数据仓库及数据集市

1735291819359.png
  • 概念

    • 数据仓库和数据集市通过ETL(数据导出、加工和导入)过程,对数据进行加工。
    • 生成报表、中间表和数据视图等,提供更高效的数据查询。
  • 日中处理

    • 每天对数据进行抽取和加工,生成数据集市。
    • 数据集市通过 T+1(数据延迟一天)的方式实现。
  • 倒排表

    • 通过倒排表(倒排索引)解决分片查询问题。
    • 例如,通过订单ID对订单明细表分片,实现高效查询。
1735291986258.png
1735291986258.png

结论

阿里巴巴禁止MySQL进行三表关联的原因主要包括产品设计要求、MySQL自身设计缺陷和数据迁移改造的困难。

为解决多表关联问题,可以采用临时性解决方案、反范式表和数据仓库及数据集市等方法。这些方法各有优缺点,需根据具体应用场景进行选择。