应优先用INNER JOIN或EXISTS替代WHERE IN子查询,避免全表扫描和NULL陷阱;LEFT JOIN过滤条件须放ON子句;UNION ALL适合日志类垂直拼接;JOIN顺序影响性能需结合EXPLAIN分析。

子查询嵌套在 WHERE 中常被误用为 JOIN 的替代
当需要根据另一张表的条件过滤主表数据时,WHERE ... IN (SELECT ...) 看似简洁,但容易触发全表扫描和重复执行。比如查“所有有订单的用户”,写成 SELECT * FROM users WHERE id IN (SELECT user_id FROM orders),MySQL 可能对每个 users 行都重跑一次子查询(尤其未加 DISTINCT 或索引时)。
更稳妥的做法是改用 INNER JOIN 或 EXISTS:
SELECT DISTINCT u.* FROM users u INNER JOIN orders o ON u.id = o.user_id;
或:
SELECT * FROM users u WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);
-
EXISTS在找到第一条匹配即停止,适合“是否存在”类判断 -
IN子查询若返回NULL,整条WHERE判断会变成UNKNOWN,导致结果为空——这是最常被忽略的逻辑陷阱 -
JOIN更利于利用索引,且执行计划通常更稳定
LEFT JOIN 后 WHERE 条件写错位置会导致隐式转 INNER JOIN
想查“所有用户及其订单数(含 0)”,却写了:
SELECT u.name, COUNT(o.id) FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.status = 'paid' GROUP BY u.id;
结果只返回有已支付订单的用户——因为 WHERE o.status = 'paid' 把 o 为 NULL 的行全过滤掉了,LEFT JOIN 形同虚设。
正确做法是把过滤条件移到 ON 子句:
SELECT u.name, COUNT(o.id) FROM users u LEFT JOIN orders o ON u.id = o.user_id AND o.status = 'paid' GROUP BY u.id;
-
ON控制“如何连接”,WHERE控制“连接后如何筛选” - 多表
LEFT JOIN时,后续表的过滤条件也必须放在对应ON中,否则会逐级收缩左表结果 - 用
EXPLAIN查看type是否为ALL,可快速识别是否意外丢失了外连接语义
JOIN 顺序影响性能,但 MySQL 8.0+ 优化器通常能自动调整
早期版本中,写 FROM large_table JOIN small_table 比反过来快,因为驱动表(large_table)决定循环次数。但现在 MySQL 优化器多数情况下会重排顺序,前提是各表有可用索引且统计信息准确。
仍需手动干预的典型场景:
- 使用了
STRAIGHT_JOIN强制顺序(如复杂视图或物化中间结果) - 某表有高选择性索引,但优化器因统计过期未选中——运行
ANALYZE TABLE更新统计信息 - 关联字段类型不一致,例如
users.id是BIGINT,而orders.user_id是INT,会导致索引失效,此时无论怎么调顺序都慢
验证方式:执行 EXPLAIN FORMAT=TREE(MySQL 8.0+),直接看优化器选定的驱动表和访问路径。
UNION ALL 比多次 JOIN 更适合“垂直拼接”类需求
当要合并不同业务类型的记录(如“用户注册日志”和“用户登录日志”),有人习惯建宽表再用 LEFT JOIN 填充空字段,结果表膨胀、查询变慢。
更自然的方式是用 UNION ALL 水平堆叠结果:
SELECT 'register' AS event_type, user_id, created_at AS event_time FROM register_log UNION ALL SELECT 'login' AS event_type, user_id, created_at AS event_time FROM login_log ORDER BY event_time DESC LIMIT 100;
-
UNION ALL不去重、不排序,性能远高于UNION - 避免在
UNION各分支里写复杂子查询——先物化到临时表或 CTE 中再拼接 - 字段名和类型需严格一致;字符串长度以最长分支为准,否则可能被截断
嵌套太深、JOIN 表太多时,优先考虑是否真需要一次性拉取全部关联数据——分页、懒加载、应用层聚合往往比单条 SQL 更可控。










