MySQL系列-优化之精准解读in和exists

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL系列-优化之精准解读in和exists 1.解读in和exists 这两个关键字的区别主要是在于子查询上面,in是独立子查询,exists是相关子查询,例如: 用in查询有员工的部门       :select dept_name from dept where id in (select dept_id from emp); 用exists查询有员工的部门:select dept_name from dept where exists (select 1 from emp where dept.id=emp.dept_id); 当然,执行结果完全一致。

MySQL系列-优化之精准解读in和exists

1.解读in和exists

这两个关键字的区别主要是在于子查询上面,in是独立子查询,exists是相关子查询,例如:

用in查询有员工的部门       :select dept_name from dept where id in (select dept_id from emp);

用exists查询有员工的部门:select dept_name from dept where exists (select 1 from emp where dept.id=emp.dept_id);

当然,执行结果完全一致。

2.in和exists的效率问题

上面的SQL语句执行的完全结果一样,那么这两个的效率如何呢?

网上也是有很多文章进行解读,总的来说就是体现一种小数据集驱动大数据集的思想。很多文章是直接说小表驱动大表,其实这样是很不准确的,因为我们可以这样【select dept_name from dept where id in (select dept_id from emp where id>5;)】这样对于子查询来说他返回的结果集与他的表没太大关系了,所以小数据集驱动大的数据集是一种更精准的说法。参考【知乎 MySQL查询语句中的IN 和Exists 对比分析

下面分析它的执行原理(关于版本5.5和5.6的区别在文章后面会说):

对于in来说,他是先执行子查询然后得到子查询的结果集,再用子查询的结果去匹配外部表。这样的话需要遍历一边刚刚的结果集,如果外部表的相应字段建立了索引的话,在匹配外部表的时候就能使用上外部表的索引了。假设子查询结果大小为M,外部表的大小为N,外部表使用B+Tree索引匹配每一条数据的时间复杂度是O(log N),那么这个总的时间复杂度就相当于O(M*log N)。

对于exists来说,他是执行外表的遍历操作(不一定是全表扫描也可能是索引扫描,但是差别不是很大),然后里面的相关子查询会利用外部表的数据对内部表进行匹配,这个时候如果内部表的相关字段建立了索引的话,匹配的时候就能走索引了。同样假设子查询结果大小为M,外部表的大小为N,内部表使用B+Tree索引匹配每一条数据的时间复杂度是O(log M),那么这个总的时间复杂度就相当于O(N*log M)。

很明显:当外表大,内部数据集小,适合适使用in。当外表小,内部数据集大,适合使用exists。

3.实践检验(mysql5.5)

mysql是一代版本一代神,很多人写博客的时候都不标注出系统环境,这样可能会造成不必要的困扰。

准备数据表如下:

可以看出在emp表的dept_id上有索引。两个表的主键都是id。

首先检验exists:执行 explain select dept_name from dept where exists (select 1 from emp where dept.id=emp.dept_id);

结果和我们想像的一样,dept表的访问类型是全表扫描,emp表的访问类型是ref。

接下来检验in:执行 explain select dept_name from dept where id in (select dept_id from emp);

咦?不对啊,没有用上外部表的主键索引,外部表的访问类型是全表扫描啊!

这是因为:mysql5.5会把in的独立子查询语句转化为exists相关子查询语句,所以才出现了上面的结果。参考【搜狐科技

在mysql5.6中则不会了,在mysql5.6中的表现和我们期待的一致,具体可以参考【深入理解MySql子查询IN的执行和优化】。

由于我的本机和服务器使用的都是5.5版本,已经是非常老的一个版本了,所以在考虑是否换成5.6或者5.7,搞不好直接换8.0了,哈哈。

4.not in和not exists

这个就比较明朗了,对于not exists来说,和exists一样会利用内部表建立好的索引,唯一的区别在于当有数据匹配的时候exists返回true而not exists返回false。

实践如下:执行SQL,explain select emp_name from emp where not exists (select 1 from dept where dept.id=dept_id);

和预期一致,外表全表扫描,内表使用上了索引。

对于not in来说,哪个表的索引的用不上,除非覆盖索引的时候用一下。

外表外表扫描,内表的查询覆盖索引,因为extra字段出现了using index,但是效率比使用索引进行查找低多了。

所以对于 not exists 和 not in 来说毫不犹豫的使用 not exists 。

5.join替代

确实,对于只查询的in和exists来说,可以用join来替代。而且用join的话我们可以更好的控制使用索引的情况,对于非外连接来说,join可以自动判断表的大小,从而使小的数据集驱动大的数据集。关于join我会在另一篇博客当中进行详细讲解。

原文地址https://blog.csdn.net/UFO___/article/details/81221983

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
5月前
|
SQL 缓存 关系型数据库
MySQL 慢查询是怎样优化的
本文深入解析了MySQL查询速度变慢的原因及优化策略,涵盖查询缓存、执行流程、SQL优化、执行计划分析(如EXPLAIN)、查询状态查看等内容,帮助开发者快速定位并解决慢查询问题。
245 0
|
3月前
|
缓存 关系型数据库 MySQL
降低MySQL高CPU使用率的优化策略。
通过上述方法不断地迭代改进,在实际操作中需要根据具体场景做出相对合理判断。每一步改进都需谨慎评估其变动可能导致其他方面问题,在做任何变动前建议先在测试环境验证其效果后再部署到生产环境中去。
201 6
|
9月前
|
SQL 关系型数据库 MySQL
MySQL进阶突击系列(07) 她气鼓鼓递来一条SQL | 怎么看执行计划、SQL怎么优化?
在日常研发工作当中,系统性能优化,从大的方面来看主要涉及基础平台优化、业务系统性能优化、数据库优化。面对数据库优化,除了DBA在集群性能、服务器调优需要投入精力,我们研发需要负责业务SQL执行优化。当业务数据量达到一定规模后,SQL执行效率可能就会出现瓶颈,影响系统业务响应。掌握如何判断SQL执行慢、以及如何分析SQL执行计划、优化SQL的技能,在工作中解决SQL性能问题显得非常关键。
|
4月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
132 2
|
11月前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
2396 10
|
4月前
|
存储 SQL 关系型数据库
MySQL 动态分区管理:自动化与优化实践
本文介绍了如何利用 MySQL 的存储过程与事件调度器实现动态分区管理,自动化应对数据增长,提升查询性能与数据管理效率,并详细解析了分区创建、冲突避免及实际应用中的关键注意事项。
195 0
|
6月前
|
存储 SQL 关系型数据库
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
|
8月前
|
存储 关系型数据库 MySQL
MySQL细节优化:关闭大小写敏感功能的方法。
通过这种方法,你就可以成功关闭 MySQL 的大小写敏感功能,让你的数据库操作更加便捷。
658 19
|
9月前
|
关系型数据库 MySQL 数据库
从MySQL优化到脑力健康:技术人与效率的双重提升
聊到效率这个事,大家应该都挺有感触的吧。 不管是技术优化还是个人状态调整,怎么能更快、更省力地完成事情,都是我们每天要琢磨的事。
243 23
|
9月前
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
423 9

推荐镜像

更多
下一篇
oss云网关配置