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 INTb.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 是否优化正确
你需要检查:
好的 JOIN 查询应该:
-
• 被驱动表使用 ref / eq_ref -
• rows 数尽量小 -
• 不出现 Using temporary / filesort
总结
JOIN 查询的优化核心是:
选对驱动表、减少扫描行数、确保加速匹配。主要优化策略包括:
• JOIN 字段必须加索引 • 小表驱动大表 • JOIN 字段类型一致 • JOIN 前先过滤(减少数据量) • 避免 SELECT * • 避免在 JOIN 条件上使用函数 • 多表 JOIN 要保证中间表索引齐全 • 使用 EXPLAIN 检查执行计划 理解 JOIN 是嵌套循环后,所有优化都水到渠成。

