SQL嵌套查询如何避免全表扫描_合理使用索引辅助子查询
IN子查询变慢因MySQL 5.6前转为嵌套循环,5.7+需满足无GROUP BY等条件才启用半连接优化;应改用EXISTS、确保索引或缓存结果。子查询里用 IN 为什么突然变慢?因为 MySQL 5.6 之前,IN (SELECT ...) 会被转成嵌套循环(NLJ),外层每行都执行一次子查询,等价于全表扫描子查询表。5.7+ 虽支持半连接优化(semi-join),但前提是子查询不能含 GROUP BY、DISTINCT、聚合函数或相关子查询。检查执行计划:看到 type: ALL 或 Extra: Using where; Using join buffer 就是危险信号把 IN (SELECT id FROM t2 WHERE ...) 改成 EXISTS (SELECT 1 FROM t2 WHERE t2.id = t1.id AND ...),让优化器更可能走索引如果必须用 IN,确保子查询结果集小且 t2.id 有索引——否则先用临时表缓存结果再 JOINWHERE 子句里写相关子查询,索引还有效吗?不一定。相关子查询(correlated subquery)每次都要重新计算,如果子查询里没用上外层字段的索引条件,就容易退化成对子表的重复全扫。典型陷阱:SELECT * FROM orders WHERE status = 'paid' AND user_id IN (SELECT id FROM users WHERE region = 'CN') —— 这里 users 表没被 orders 驱动,region 索引可能被忽略改写优先级:能 JOIN 就别用相关子查询;JOIN 后加 WHERE 过滤,比在子查询里过滤更易命中索引如果非用不可,确保子查询中用于关联的字段(如 users.id)和过滤字段(如 users.region)都有联合索引,比如 INDEX(region, id)子查询返回多列时,SELECT * 会拖垮性能?会。尤其是子查询作为派生表(derived table)出现在 FROM 子句时,MySQL 会物化结果到临时表,默认用 MyISAM(旧版)或 InnoDB(8.0+),没索引、不压缩、全字段存储。 Cleanup.pictures 智能移除图片中的物体、文本、污迹、人物或任何不想要的东西
