MySQL中in和exists的使用场景

news2025/3/12 9:02:24

在MySQL中,INEXISTS 是用于子查询的两种常见方法,它们在不同的场景下有不同的表现和适用性。下面我将详细介绍这两种方法的使用场景、优劣,并通过实验来说明问题。

IN 子查询

使用场景:

  • 当子查询返回的结果集较小且不包含 NULL 值时。
  • 当需要检查一个值是否存在于子查询结果集中时。

优点:

  • 语法简单直观。
  • 对于小数据集,性能较好。

缺点:

  • 当子查询返回的结果集较大时,性能可能较差。
  • 如果子查询结果集中包含 NULL 值,IN 子查询会返回空结果集。

EXISTS 子查询

使用场景:

  • 当需要检查子查询是否返回任何行时。
  • 当子查询返回的结果集较大或包含 NULL 值时。

优点:

  • 对于大数据集,性能较好。
  • 即使子查询结果集中包含 NULL 值,EXISTS 子查询也能正常工作。

缺点:

  • 语法相对复杂一些。
  • 对于小数据集,性能可能不如 IN 子查询。

实验说明

假设我们有两个表 employeesdepartments,结构如下:

CREATE TABLE employees (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    department_id INT
);

CREATE TABLE departments (
    id INT PRIMARY KEY,
    name VARCHAR(100)
);

插入一些示例数据:

INSERT INTO departments (id, name) VALUES (1, 'HR'), (2, 'Engineering'), (3, 'Marketing');

INSERT INTO employees (id, name, department_id) VALUES 
(1, 'Alice', 1), 
(2, 'Bob', 2), 
(3, 'Charlie', 2), 
(4, 'David', 3), 
(5, 'Eve', NULL);
使用 IN 子查询
SELECT * FROM employees WHERE department_id IN (SELECT id FROM departments WHERE name = 'Engineering');

这个查询会返回 BobCharlie,因为他们属于 Engineering 部门。

使用 EXISTS 子查询
SELECT * FROM employees e WHERE EXISTS (SELECT 1 FROM departments d WHERE d.id = e.department_id AND d.name = 'Engineering');

这个查询也会返回 BobCharlie,因为存在 Engineering 部门并且 BobCharlie 属于该部门。

性能比较

为了比较 INEXISTS 的性能,我们可以使用一个更大的数据集进行测试。假设我们有 100,000 条员工记录和 100 个部门记录。

-- 插入大量数据
INSERT INTO departments (id, name)
SELECT id, CONCAT('Department ', id) FROM (SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10) a,
(SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10) b,
(SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10) c;

INSERT INTO employees (id, name, department_id)
SELECT id, CONCAT('Employee ', id), FLOOR(RAND() * 100) + 1
FROM (SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10) a,
(SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10) b,
(SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10) c,
(SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10) d,
(SELECT 1 AS id UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10) e;

然后我们分别执行以下两个查询并比较性能:

-- 使用 IN 子查询
SELECT * FROM employees WHERE department_id IN (SELECT id FROM departments WHERE name LIKE 'Department%');

-- 使用 EXISTS 子查询
SELECT * FROM employees e WHERE EXISTS (SELECT 1 FROM departments d WHERE d.id = e.department_id AND d.name LIKE 'Department%');

通常情况下,对于大数据集,EXISTS 子查询的性能会更好,因为它在找到第一个匹配项后就会停止搜索,而 IN 子查询需要先获取所有匹配项再进行比较。

结论

  • IN 子查询适用于子查询结果集较小且不包含 NULL 值的情况,语法简单直观。
  • EXISTS 子查询适用于子查询结果集较大或包含 NULL 值的情况,对大数据集性能更好。

在实际应用中,应根据具体场景选择合适的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2262416.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VMware虚拟机Ubuntu 18.04版本 磁盘扩容

一、版本配置 虚拟机版本:VMware WORKSTATION 16 PRO Ubuntu版本:Ubuntu 18.04 二、磁盘大小介绍 目的:磁盘扩容(20G----->100G),从20G扩到100G 查看磁盘大小命令:df -h 扩容前的磁盘大小 …

QT多线程(二):基于互斥锁与读写锁的线程同步

此处需要说明的是,这里的线程同步概念与操作系统中的线程同步并无区别,都是避免多个线程同时访问临界区数据可能产生的读写错误问题。在 Qt 中,有多个类可以实现线程同步的功能,这些类包括 QMutex、QMutexLocker、 QReadWriteLock…

【ChatGPT】解锁AI思维链:如何让机器像人类一样思考?

在人工智能领域,我们一直在追求让机器像人类一样思考。然而,即使是最先进的AI,也常常被诟病缺乏“常识”,难以理解复杂问题,更不用说像人类一样进行逻辑推理和解决问题了。最经常的表现就是遇到不会的地方,…

重新定义页签!Choerodon UI Tabs让管理更高效

01 引言 Tabs 组件通过提供平级区域,将大块内容进行有效的收纳和展现,从而保持界面整洁。但在企业应用的快速发展中,这样传统的页签组件已无法满足我们对界面布局和个性化展示的追求。Choerodon UI Tabs 组件通过支持多级分组、个性化配置、…

机器学习之偏差

机器学习中的偏差(Bias)是指模型的预测值与真实值之间的系统性误差,或者说模型无法准确捕捉数据中复杂模式的能力。偏差通常与模型的假设或学习能力有关,过高的偏差会导致模型的性能不佳,表现为欠拟合。 偏差的来源 模…

SSH连接监控以及新用户创建和系统资源访问限制

目录 监控连接数SSH连接数的限制和影响理论限制可能的影响 创建SSH新用户为每个ssh用户配置系统资源限制1. 使用 /etc/security/limits.conf 限制资源2. 使用 cgroups 控制资源3. 磁盘配额限制4. 限制 SSH 访问5. 使用 PAM 限制6. 监控脚本示例7. 设置定期任务清理8. 检查配置是…

测试工程师八股文04|计算机网络 和 其他

一、计算机网络 1、http和https的区别 HTTP和HTTPS是用于在互联网上传输数据的协议。它们都是应用层协议,建立在TCP/IP协议栈之上,用于客户端(如浏览器)和服务器之间的通信。 ①http和https的主要区别在于安全性。http是一种明…

单片机学习笔记——入门51单片机

一、单片机基础介绍 1.何为单片机 单片机,英文Micro Controller Unit,简称MCU 。内部集成了中央处理器CPU、随机存储器ROM、只读存储器RAM、定时器/计算器、中断系统和IO口等一系列电脑的常用硬件功能 单片机的任务是信息采集(依靠传感器&a…

【青牛科技】D8563是低功耗的CMOS实时时钟/日历电路,它提供一个可编程时钟输出,一个中断输出和掉电检测器,所有的地址和数据通过IC总线接口串行传递。

概述: D8563是低功耗的CMOS实时时钟/日历电路,它提供一个可编程时钟输出,一个中断输出和掉电检测器,所有的地址和数据通过IC总线接口串行传递。最大总线速度为400Kbitss每次读写数据后,内嵌的字地址寄存器会自动产生增量。 主要特…

安卓获取所有可用摄像头并指定预览

在Android设备中,做预览拍照的需求的时候,我们会指定 CameraSelector DEFAULT_FRONT_CAMERA前置 或者后置CameraSelector DEFAULT_BACK_CAMERA 如果你使用的是平板或者工业平板,那么就会遇到多摄像头以及外置摄像头问题,简单的指…

R语言学习笔记-1

1. 基础操作和函数 清空环境:rm(list ls()) 用于清空当前的R环境。 打印输出:print("Hello, world") 用于输出文本到控制台。 查看已安装包和加载包: search():查看当前加载的包。install.packages("package_na…

Windows如何安装go环境,离线安装beego

一、安装go 1、下载go All releases - The Go Programming Language 通过网盘分享的文件:分享的文件 链接: https://pan.baidu.com/s/1MCbo3k3otSoVdmIR4mpPiQ 提取码: hxgf 下载amd64.zip文件,然后解压到指定的路径 2、配置环境变量 需要新建两个环境…

Mac上使用ln指令创建软链接、硬链接

在Mac、Linux和Unix系统中,软连接(Symbolic Link)和硬连接(Hard Link)是两种不同的文件链接方式。它们的主要区别如下: 区别: 硬连接: 不能跨文件系统。不能链接目录(为…

Unity A*算法实现+演示

注意: 本文是对基于下方文章链接的理论,并最终代码实现,感谢作者大大的描述,非常详细,流程稍微做了些改动,文末有工程网盘链接,感兴趣的可以下载。 A*算法详解(个人认为最详细,最通俗易懂的一…

博弈论3:图游戏SG函数(Graph Games)

目录 一、图游戏是什么 1.游戏特征 2.游戏实例 二、图游戏的必胜策略 1.SG 函数(Sprague-Grundy Function) 2.必胜策略(利用SG函数) 3.拿走游戏转化成图游戏(Take-away Game -> Graph Game) 一、图…

0101多级nginx代理websocket配置-nginx-web服务器

1. 前言 项目一些信息需要通过站内信主动推动给用户,使用websocket。web服务器选用nginx,但是域名是以前通过阿里云申请的,解析ip也是阿里云的服务器,甲方不希望更换域名。新的系统需要部署在内网服务器,简单拓扑图如…

qt-C++笔记之自定义类继承自 `QObject` 与 `QWidget` 及开发方式详解

qt-C笔记之自定义类继承自 QObject 与 QWidget 及开发方式详解 code review! 参考笔记 1.qt-C笔记之父类窗口、父类控件、对象树的关系 2.qt-C笔记之继承自 QWidget和继承自QObject 并通过 getWidget() 显示窗口或控件时的区别和原理 3.qt-C笔记之自定义类继承自 QObject 与 QW…

Elastic 8.17:Elasticsearch logsdb 索引模式、Elastic Rerank 等

作者:来自 Elastic Brian Bergholm 今天,我们很高兴地宣布 Elastic 8.17 正式发布! 紧随一个月前发布的 Elastic 8.16 之后,我们将 Elastic 8.17 的重点放在快速跟踪关键功能上,这些功能将带来存储节省和搜索性能优势…

[C++]类的继承

一、什么是继承 1.定义: 在 C 中,继承是一种机制,允许一个类(派生类)继承另一个类(基类)的成员(数据和函数)。继承使得派生类能够直接访问基类的公有和保护成员&#xf…

Docker 用法详解

文章目录 一、Docker 快速入门1.1 部署 MYSQL1.2 命令解读: 二、Docker 基础2.1 常见命令:2.1.1 命令介绍:2.1.2 演示:2.1.3 命令别名: 2.2 数据卷:2.2.1 数据卷简介:2.2.2 数据卷命令&#xff…