MySQL 中 EXISTS 和 IN 的区别是什么?

Sherwin.Wei Lv7

MySQL 中 EXISTS 和 IN 的区别是什么?

回答重点

基本功能

  • EXISTS 用于判断子查询是否返回任何行,通常用于检查某个条件是否满足。
  • IN 用于检查某个值是否在指定的集合中,可以是一个子查询或静态值列表。

性能差异

  • EXISTS 一旦找到匹配行就会立即返回,通常在子查询返回较大数据集时性能更好。
  • IN 通常会评估整个子查询并构建一个值列表,然后再进行匹配,在处理较大数据集时可能性能较差。

使用场景

  • EXISTS 更适合用于大数据量或复杂逻辑的条件判断。
  • IN 更适合简单的静态值集合或较小的子查询结果。

扩展知识

进一步分析 EXISTS 和 IN 性能问题

EXISTS

EXISTS 的查询机制是循环外表,通过外表的每行数据去内表查询是否有匹配的值,一旦找到符合条件的记录,此次内表子查询就会停止执行。然后再通过下一个外表的值来查询,如此循环。

1
2
SELECT * FROM `mianshiya` 
WHERE exists (SELECT * FROM `order` WHERE mianshiya.user_id = order.user_id)

例如 mianshiyia 表有 100 条数据,order有 10000 条数据,那么 EXISTS 会执行 100 次去 order 中查询判断 mianshiyia的 user_id 和 order user_id 是否相等。

所以它适合子查询中表比外表大且有索引的场景

IN

而 IN 子查询在执行时会先执行子查询并生成结果集,然后将结果集与外部查询的列进行比较,所以它适合子查询记录少,且主查询表大有索引的场景

1
2
SELECT * FROM `mianshiya`  
WHERE user_id in (SELECT user_id FROM `order`)

同样 mianshiyia_user 表有 100 条数据,order有 10000 条数据,那么 in 操作会先执行子查询获取 order 的 10000 条数据这个结果集放在缓存中。

如果 mianshiyia_user user_id 上有索引则可以利用索引查询,不然就是逐行检查 mianshiyia_user 中的 user_id 是否与结果集中的 user_id 一致执行,因此一共会进行 100*10000 次对比。

如果子查询得到的结果比较大,还会将子查询的结果存储在哈希表中,这样就能快速匹配数据。

简单总结

  • 外层查询表量级小于子查询表,且子表有索引,则用 exists
  • 外层查询表量级大于子查询表,且外层表有索引,则用 in
  • 如果外层和子查询表差不多,则都行。

建议具体情况还是以 explain 分析为主

Comments