当前位置: 首页 > news >正文

MySQL中的in和exists的区别

从效果上看:

  1. IN运算符:是看某个值是否存在于一个集合里。这个集合可以是静态列表,也可以是子查询。
  2. EXISTS运算符:用于判断一个子查询是否有结果,他只关心子查询是否返回了至少一行结果,不关心具体返回什么。

从性能上看:

  1. IN从语义上来说,是会先执行子查询,然后把列表确定了,之后再用外层表的每一行记录去看某个字段的值是否IN的列表里面存在,存在就返回。比如select * from A where A.id in (select B.a_id from B),会使用A表的每一行记录去执行select 1 from B where B.id=A.id,因为in的字段是可以使用索引的(这里的A.id可以使用索引),所以适合外层表有相关字段有索引的情况。有索引时,外层表的相关字段有索引时相当于是走**range** 扫描,性能极高(类似多个 **=** 查询的合并)。但是这个也不一定,因为MySQL优化器可能会进行优化。比如SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE status = ‘paid’);MySQL在IN里面是子查询,并且子查询是的user_id字段有索引,那么可能 会 **IN** 转换为 **JOIN** **EXISTS**(这个要看优化器的选择了)。
  2. EXISTS 从语义上来说,他是外层表驱动内层表的,即,EXISTS外层表的每一行都会去执行子查询,所以外层的表数量要尽量少一些,内层表的查询速度要尽量快一些。比如select * from A where exist(select 1 from B where B.id=A.id),会使用A表的每一行记录去执行select 1 from B where B.id=A.id,只要存在一个能匹配的数据,就返回A的这一行数据。exists时候外层数据量少的,子查询比较大的,并子查询中可以利用索引的情况。这样的话,效率也不会低,因为外层循环少,内层可以利用索引,就算数据量大,但是查询也不慢,所以速度快。

但是实际上的性能不一定是上面分析的这样的,因为MySQL的优化器可能会对他们进行优化,你写的in可能会被优化为exist,所以谁效率高谁效率低还是要看实际的执行效果的。

注意:尽量不要使用not in,因为not in后面的集合中,如果存在null,那么结果一定是空。所以可能会导致你判断错误,你给他一个列表,想拿到列表中存在的数据,但是不小心放进去一个null值,结果一条数据也找不到了。

比如

-- 使用 IN:查找有订单的用户
SELECT * FROM sys_user 
WHERE user_id IN (SELECT user_id FROM sys_order);
/* 结果:Alice (1), Bob (2)说明:IN 忽略子查询中的 NULL 值 */-- 使用 EXISTS:查找有订单的用户
SELECT * FROM sys_user u
WHERE EXISTS (SELECT 1 FROM sys_order o WHERE o.user_id = u.user_id
);
/* 结果:Alice (1), Bob (2)说明:EXISTS 同样忽略 NULL */
-- ⚠️ 危险示例:使用 NOT IN(含 NULL)
SELECT * FROM sys_user 
WHERE user_id NOT IN (SELECT user_id FROM sys_order);
/* 结果:空集!(即使 Charlie 没有订单)原因:子查询包含 NULL => 整个条件无效 */-- ✅ 安全方案:使用 NOT EXISTS
SELECT * FROM sys_user u
WHERE NOT EXISTS (SELECT 1 FROM sys_order o WHERE o.user_id = u.user_id
);
/* 结果:Charlie (3)说明:正确找到无订单用户 */

结论:

"NOT IN 后的集合如果存在 NULL,结果一定是空"
"永远用 NOT EXISTS 替代 NOT IN"

http://www.lryc.cn/news/616387.html

相关文章:

  • C++多线程服务器
  • Spring循环依赖详解
  • MySQL面试题及详细答案 155道(041-060)
  • LeeCode 46. 全排列
  • 冒泡排序实现以及优化
  • 20250810 | 深度学习入门笔记1
  • 大型动作模型LAM:让企业重复任务实现80%效率提升的AI技术架构与实现方案
  • 五种 IO 模型与阻塞 IO
  • 数组中的第K个最大元素
  • MyBatisPlus插件原理
  • Leetcode 3646. Next Special Palindrome Number
  • 代码随想录算法训练营第六十天|图论part10
  • 【Nginx②】 | Nginx部署前端静态文件指南(基于虚拟机环境)
  • 浏览器CEFSharp88+X86+win7 之多页面展示(四)
  • NodeJs学习日志(4):路由合并_环境配置_常用文件目录
  • element-ui el-progress在有小数的情况下,会换行显示。解决不换行的问题。
  • iceberg安装部署
  • Rust面试题及详细答案120道(11-18)-- 控制流与函数
  • vulnhub-Drippingblues靶机
  • 通过Certbot自动申请更新HTTPS网站的SSL证书
  • 瑞芯微 RK3588 平台驱动开发 学习计划
  • CST支持对哪些模型进行特征模仿真?分别有哪些用于特征模分析的求解器?
  • C语言——深入理解指针(二)
  • 【东枫科技】FR3 可扩展测试平台,适用于 6G 研究与卫星通信,高达 1.6 GHz 的带宽
  • 【秋招笔试】2025.08.09美团秋招算法岗机考真题-第三题
  • Python 的浅拷贝 vs 深拷贝(含嵌套可变对象示例与踩坑场景)
  • OpenGL VAO 概念、API 和示例
  • 每日一题:使用栈实现逆波兰表达式求值
  • TypeScript中的type和interface的区别是什么?
  • 从街亭失守看管理