来源 | 君哥聊技术(ID:gh_1f109b82d301)
多表 JOIN 是好多公司严格禁止的 SQL 写法,那它到底有哪些危害呢?今天来聊一下这个话题。

1.资源压力
多表 JOIN,尤其是 JOIN 涉及的表存在大表的情况下,数据库会承受巨大的计算和内存压力。
在高并发场景下,多表 JOIN 可能占用大量的 join buffer,
造成内存压力增加,SQL 执行时间增大,进一步造成大量连接不能释放,连接被耗尽。最终结果就是整个数据库实例响应慢,客户端因为获取不到连接而失败。
2.性能风险
JOIN 语句的性能依赖于正确的索引,如果 ON 或 WHERE 子句中的列没有加索引,执行 JOIN 语句需要进行全表扫描。JOIN 的表越多,全表扫描的成本越高,最坏情况下可能达到呈笛卡尔积的数量级。尤其是 JOIN 语句中有大表(比如数据量百万级别)时,一个复杂的多表 JOIN 语句响应时间可能会达到分钟级别,这会造成大量上游系统请求超时,业务不能正常进行。
3.锁等待
InnoDB 默认隔离级别是可重复读,在可重复读隔离级别下,JOIN
查询可能会对涉及的行加间隙锁,如果 JOIN 的表比较多,可以会有多张表的多条记录和间隙被锁定,造成其他事务的锁等待,甚至可能造成死锁,这会严重降低系统吞吐量。
4.可维护性差
多表 JOIN 的 SQL 涉及多张表、多个 JOIN 条件,往往 where 子句也会有多个筛选条件,可读性差。而复杂 JOIN 往往包含了复杂业务逻辑,面对需求修改,如果不是 SQL 原作者,很难理解和维护。对测试而言,测试用例也很难覆盖所有场景,导致生成问题。
5.影响分库分表
随着业务量上升,数据量也会变大,单表存储会影响到 SQL 性能,这个时候就需要考虑分库分表。如果一个多张表 JOIN 的 SQL 语句中涉及多张表要分库和分表,那就必须让这些表的同一笔业务数据拆分到同一个数据库节点上,同时 JOIN 的表名也需要修改,这涉及的改造和测试 工作难度非常大。
6.影响信创改造
如果涉及信创改造,多表 JOIN 的 SQL 除了数据迁移外,还需要评估这个 SQL 在新库上的执行效率,给信创改造增加了很多额外的工作。