概念

语法 用途 常用场景
IN 判断是否在某个列表 列表是静态值(IN (1,2,3))或子查询
EXISTS 判断是否存在匹配 子查询里经常配合外层列
JOIN 真正把两表关联起来,输出结果 需要拿到匹配列时

底层

IN EXISTS JOIN
执行原理 将子查询结果先计算成一个临时集合,外层值去匹配 外层值带进去跑子查询,看是否至少存在一行 两张表做笛卡尔积 + 连接条件过滤,或用索引、Hash Join、Nested Loop 加速
适用场景 小范围列表/短子查询结果 子查询通常跟外层值有关(correlated subquery) 需要输出连接列
优化器行为 INEXISTS 常可相互转换 INEXISTS 有时会改写成半连接 JOIN 可以是 Nested Loop / Hash Join / Merge Join

性能

场景 谁更快
IN (静态值) vs EXISTS IN 更快(因为直接转 OR)
IN (子查询) vs EXISTS (子查询) 大多数情况下 EXISTS 更优,尤其是子查询和外层相关时
JOIN vs EXISTS 如果只是判断是否匹配,EXISTSJOIN 更省内存,不会产生笛卡尔积;JOIN 在需要取出列时更方便

何时用

需求 推荐
判断某值是否属于固定列表 IN
判断是否存在匹配记录 EXISTS
需要取匹配行的列 JOIN
子查询和外层列有依赖关系 EXISTS 通常比 IN 更优
大集合匹配 优先 JOIN(配合索引)

示例

写法 解释
WHERE id IN (1, 2, 3) 最快,直接 OR
WHERE id IN (SELECT id FROM big_table) 如果 big_table 很大,EXISTS 更合适
WHERE EXISTS (SELECT 1 FROM big_table WHERE big_table.id = small_table.id) 如果 big_table 有索引,EXISTS 很快
JOIN 如果要输出 big_table 的列,必须用 JOIN

实战经验

  • IN 的子查询结果集比较大时会变慢(内部先 materialize)

  • EXISTS 通常对相关子查询更友好(会 index lookup)

  • JOIN 要注意是否会产生重复行(笛卡尔积),如果只需要“是否有匹配”,不要用 JOIN

判断方法

一定要看 EXPLAIN

因为 MySQL 优化器有时会把:

  • IN 改成 EXISTS

  • EXISTS 改成 Semi-Join

  • JOIN 改成 Hash Join

你只要记住:
只需判断是否存在:用 EXISTS
小范围值匹配:用 IN
要输出匹配的列:用 JOIN

 

作者 admin

百度广告效果展示