当前位置: 首页 > 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.dtcms.com/a/324678.html

相关文章:

  • mmdetection3d中centerpoint解析
  • FPGA常用资源之IO概述
  • Mybatis学习之动态SQL(八)
  • 使用GLib D-Bus 库创建dbus服务端
  • 安全运维的核心
  • 使用 iFLOW-CLI GitHub Action 和 Qwen3-Coder 给 GitHub 仓库生成幻灯片风格的文档站点
  • 一个基于 Next.js 和 Puppeteer 的 Markdown 转图片服务,支持 Docker 部署和 API 集成
  • AI绘画:生成唐初秦叔宝全身像提示词
  • reuse: for booting my spring project with mvn in Windows command line
  • 理清C语言中内存操作的函数
  • LeetCode_字符串
  • 《C语言》结构体和联合体练习题--1
  • ROS2 学习笔记
  • 基于百度地图API的社区地图展示技术实现
  • 初识STL
  • ADB简介
  • 【redis初阶】--------Set 集合类型
  • Baumer高防护相机如何通过YoloV8深度学习模型实现道路坑洼的检测识别(C#代码UI界面版)
  • Linux操作系统从入门到实战(十六)冯诺依曼体系结构,操作系统与系统调用和库函数概念
  • API 接入终极指南:实时掌握京东商品动态
  • openpnp - 顶部相机如果超过6.5米影响通讯质量,可以加USB3.0信号放大器延长线
  • SpringAI报错:com.github.victools.jsonschema.generator.AnnotationHelper
  • 北京-4年功能测试2年空窗-报培训班学测开-第七十二天
  • Langchain入门:构建一个本地RAG应用
  • 《Go小技巧易错点100例》第三十七篇
  • 深度解析Linux设备树(DTS):设计原理、实现框架与实例分析
  • 阿里云ECS云服务器临时升级带宽方法
  • JP3-4-MyClub后台前端(三)
  • 胖虎的菜品
  • 一劳永逸解决Mayplotlib绘图中中文字体显示乱码的问题