大数跨境
0
0

MYSQL JOIN 查询的优化策略

MYSQL JOIN 查询的优化策略 Linux运维技术之路
2025-11-23
3
导读:MYSQL JOIN 查询的优化策略

 










 

Mysql  JOIN 查询的优化策略

JOIN 是复杂查询中最常出现的操作,但如果不优化,会导致:

  • • CPU 飙升
  • • 扫描上百万行
  • • JOIN Buffer 暴涨
  • • 查询慢到怀疑人生

下面我用最实用的方式总结 JOIN 的最佳优化策略,让你从根本上提升 SQL 性能。


一、明确 JOIN 的执行原理(优化的前提)

MySQL JOIN 的本质是“嵌套循环”(Nested Loop Join):


   
    
   外层表取一行 → 内层表找匹配行

因此要记住:

JOIN 的性能 = 外层表扫描 + 内层表查找效率
优化 JOIN 的核心:减少扫描行数,提高匹配效率

也就是说:

✔ 选对驱动表(小表)
✔ 确保被驱动表的 JOIN 字段有索引
✔ 尽量减少需要 JOIN 的数据量

理解这一点,后面所有优化策略都顺理成章。


二、JOIN 字段必须有索引(最重要!)

典型 JOIN 语句:


   
    
   SELECT *
FROM
 orders o
JOIN
 users u ON o.user_id = u.id;

为了加速 JOIN:

  • • 被驱动表(通常是右表) JOIN 字段必须要索引
  • • 例如 users.id 必须建立索引(通常是主键)

否则 MySQL 会对被驱动表执行 全表扫描,性能恶化。


三、优先使用小表作为驱动表(Small Table Drive Big Table)

JOIN 中顺序很关键:


   
    
   左表扫描越少,整个 JOIN 越高效。

例如:


   
    
   SELECT *
FROM
 big_table b
JOIN
 small_table s ON b.s_id = s.id;

可能非常慢,因为 big_table 是驱动表。

优化:


   
    
   SELECT *
FROM
 small_table s
JOIN
 big_table b ON b.s_id = s.id;

或使用 STRAIGHT_JOIN 强制执行顺序:


   
    
   SELECT STRAIGHT_JOIN *
FROM
 small_table s
JOIN
 big_table b ON b.s_id = s.id;

四、JOIN 条件必须使用同类型字段

例如:

s.id INT
b.s_id VARCHAR

JOIN 过程中 MySQL 会做类型转换,导致索引失效。

👉 JOIN 字段必须类型一致。


五、尽量减少 JOIN 前的数据量

任何能“提前过滤”的操作都应该放在 JOIN 之前。

不推荐:


   
    
   SELECT *
FROM
 orders o
JOIN
 users u ON o.user_id = u.id
WHERE
 u.status = 1;

推荐(先过滤,再 JOIN):


   
    
   SELECT *
FROM
 orders o
JOIN
 (SELECT id FROM users WHERE status = 1) u
ON
 o.user_id = u.id;

这样 JOIN 只做必要数据量。


六、多表 JOIN 时,给中间表加索引

例如三表连接:


   
    
   A JOIN B ON A.id = B.a_id
JOIN C ON B.c_id = C.id

很多人只给 C.id 加索引,忽略中间表。

正确做法:

  • • B.a_id 必须索引(加速 A → B)
  • • B.c_id 必须索引(加速 B → C)
  • • C.id 本身索引

中间表尤为关键!


七、避免在 JOIN 条件上做函数或表达式

❌ 不能这样:


   
    
   JOIN user u ON DATE(u.create_time) = o.day

函数会使索引失效。

✔ 应这样:


   
    
   JOIN user u ON u.create_time >= o.day
             AND
 u.create_time < o.day + INTERVAL 1 DAY;

*八、避免 SELECT ,只查询必要字段

JOIN 会导致:

  • • 读取大量无用列
  • • JOIN Buffer 增大
  • • 回表次数增加

优化:


   
    
   SELECT o.id, o.price, u.name
FROM
 orders o
JOIN
 users u ON o.user_id = u.id;

特别是大字段(TEXT/BLOB),千万不要 SELECT *。


九、控制 JOIN Buffer 的使用

当索引不足时,MySQL 会使用 JOIN BUFFER 进行块匹配,但 JOIN BUFFER 越大,磁盘 IO 越多,性能越差。

要避免:

  • • JOIN 条件没索引
  • • 大量 FULL JOIN
  • • 无条件 JOIN

十、尽量用 INNER JOIN 替代 LEFT JOIN

LEFT JOIN 会使 MySQL 认为“右表必须全部扫描”,很多优化策略无法使用。

如果业务允许,尽量 INNER JOIN:


   
    
   INNER JOIN 只保留匹配的记录,优化空间最大
LEFT
 JOIN   可能导致扫描更多数据

十一、分区表 JOIN:确保分区列参与过滤

否则 JOIN 时参与表会被全分区扫描,性能极差。


十二、使用 EXPLAIN 检查 JOIN 是否优化正确

你需要检查:

EXPLAIN 字段
判断方向
type
是否为 ref、eq_ref(最优)
key
是否走上索引
rows
扫描行数是否太多
extra
是否出现 Using temporary、Using filesort

好的 JOIN 查询应该:

  • • 被驱动表使用 ref / eq_ref
  • • rows 数尽量小
  • • 不出现 Using temporary / filesort

总结

JOIN 查询的优化核心是:
选对驱动表、减少扫描行数、确保加速匹配。

主要优化策略包括:

  • • JOIN 字段必须加索引
  • • 小表驱动大表
  • • JOIN 字段类型一致
  • • JOIN 前先过滤(减少数据量)
  • • 避免 SELECT *
  • • 避免在 JOIN 条件上使用函数
  • • 多表 JOIN 要保证中间表索引齐全
  • • 使用 EXPLAIN 检查执行计划

理解 JOIN 是嵌套循环后,所有优化都水到渠成。

 




 

 


往期回顾


【声明】内容源于网络
0
0
Linux运维技术之路
专注运维架构、高可用、高并发、高性能、大数据、容器化、数据库、python、devops等开源技术和实践的分享。
内容 347
粉丝 0
Linux运维技术之路 专注运维架构、高可用、高并发、高性能、大数据、容器化、数据库、python、devops等开源技术和实践的分享。
总阅读736
粉丝0
内容347