首页/数据/SQL 速查/子查询改写为连接的取舍
性能与执行计划72 条

子查询改写为连接的取舍

IN/EXISTS 子查询与 JOIN 在多数优化器下可得到等价执行:语义差异(去重、NULL)决定改写方向。

SQL 速查数据更新于 2026-10-12

示例

示例
-- EXISTS:存在性判断,语义清晰
SELECT u.id, u.name
FROM users u
WHERE EXISTS (SELECT 1 FROM orders o WHERE o.user_id = u.id);

-- 等价 JOIN + 去重
SELECT DISTINCT u.id, u.name
FROM users u
JOIN orders o ON o.user_id = u.id;

-- 需要计数/聚合时应直接用 LEFT JOIN
SELECT u.id, COUNT(o.id) AS cnt
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id;
EXISTS半连接语义:只判断存在,不产生重复行
IN与 EXISTS 常可互换;NOT IN 有 NULL 陷阱,建议改写为 NOT EXISTS
优化器MySQL 有半连接优化策略;PG 通常产生 Semi Join 类计划

易错点

  • 为了“优化”一律把 EXISTS 改 JOIN:连接放大可能迫使外层加 DISTINCT,反而更贵
  • 保留 NOT IN 不改写:列含 NULL 时结果可能为空,语义与性能双输

数据来源与参考

  • MySQL 8.0 Reference Manual · Optimizing Subqueries
  • PostgreSQL Documentation · Subquery Expressions
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌