为什么在 MySQL 中不推荐使用多表 JOIN?

Sherwin.Wei Lv7

为什么在 MySQL 中不推荐使用多表 JOIN?

回答重点

性能问题

  • 多表 JOIN 可能导致查询性能下降,尤其是在处理大数据集时,JOIN 操作的计算复杂度会显著增加,需要进行大量的数据扫描和匹配,增加了内存和CPU的消耗,导致响应时间变长。

可读性和维护性

  • 多表 JOIN 的查询语句较为复杂,降低了 SQL 的可读性和可维护性。复杂的语句可能会增加错误发生的概率,使得后续的调试和优化更加困难。

扩展知识

多表 JOIN

这里的多表往往指的是超过三个表才是多表,正常两个表 join 是没问题的!(但是也需要评估下量级和是否命中索引)

阿里的 Java 规范手册里也有一句话:“超过三个表禁止使用 Join”。

这是为什么呢?

其实数据量小都无所谓。但当数据量大的时候,影响就被放大了。如果让数据库来承担这个复杂的关联操作,需要对联接的每个表进行扫描、匹配和组合,消耗大量的 CPU 和内存资源。让复杂的关联操作占用了大量的数据库资源,会影响其他查询修改操作。

数据库往往是我们系统的弱点,很多情况下性能瓶颈都在数据库,因此我们需要尽量避免把压力放在数据库上

所以不推荐多表 Join。

Join 时候的注意点

Join 的时候,需要关注被驱动表的查询是否能命中索引,不然就会导致全表扫描。

并且尽量让小表做驱动表,因为驱动表需要全表扫描,而被驱动表是通过索引查询的。

我们简单看下面的例子来理解一下:

例如执行 select * from mianshiya1 straight_join mianshiya2 on (mianshiya1.a=mianshiya2.a);

straight_join 是指定的链接,让 mianshiya1 作为驱动表,mianshiya2 作为被驱动表

这条语句就需要全表扫描 mianshiya1 ,然后将其中的 a 字段作为查询条件去 mianshiya2 进行搜索,所以我们要求 mianshiya2 的 a 字段有索引,这样查询的比较快。

那为什么要让小表作为驱动表呢?

假设驱动表 mianshiya1 的数据量为 A,被驱动表为 B,全表扫描驱动表的行数为 A ,每次扫描被驱动表 mianshiya2 命中二级索引,是搜索树,理论上查询一次的时间复杂度是 log2B ,可能还需要回表查询主键索引,也是搜索树,那么需要乘 2,所以是 2log2B

一共要查询 A 次,因此整体的执行复杂度是 A+2log2B*A

很显然,A 的值越大,时间复杂度越高,所以我们得让 A 小,所以选择小表驱动!

Comments