Mysql查询优化之IN子查询优化方法详解

 更新时间:2023年02月09日 14:36:32   作者:云深n不知处  
项目中有需要,使用MySQL的in子查询,查询符合in子查询集合中条件的数据,但是没想到的是,MySQL的in子查询会如此的慢,让人无法接受,下面这篇文章主要给大家介绍了关于Mysql查询优化之IN子查询优化的相关资料,需要的朋友可以参考下

物化表

首先提出一个不相关的IN子查询

SELECT * FROM s1 
 WHERE key1 IN (SELECT common_field FROM s2 WHERE key3 = 'a');

对于不相关的 IN 子查询来说,如果子查询的结果集中的记录条数很少,那么把子查询和外层

查询分别看成两个单独的单表查询效率还是蛮高的,但是如果单独执行子查询后的结果集太多的话,就会导致这
些问题:

  • 结果集太多,可能内存中都放不下~
  • 对于外层查询来说,如果子查询的结果集太多,那就意味着 IN 子句中的参数特别多,这就导致:

无法有效的使用索引,只能对外层查询进行全表扫描。
在对外层查询执行全表扫描时,由于 IN 子句中的参数太多,这会导致检测一条记录是否符合和 IN 子句中的参数匹配花费的时间太长。
比如说 IN 子句中的参数只有两个:
SELECT * FROM tbl_name WHERE column IN (a, b);
这样相当于需要对 tbl_name 表中的每条记录判断一下它的 column 列是否符合 column = a OR column= b 。在 IN 子句中的参数比较少时这并不是什么问题,如果 IN 子句中的参数比较多时,比如这样:
SELECT * FROM tbl_name WHERE column IN (a, b, c …, …);
那么这样每条记录需要判断一下它的 column 列是否符合 column = a OR column = b OR column = c
OR … ,这样性能耗费可就多了。

所以提出一个解决方案:不直接将不相关子查询的结果集当作外层查询的参数,而是将该结果集写入一个临时表里。

临时表的特性:

  1. 该临时表的列就是子查询结果集中的列。
  2. 写入临时表的记录会被去重。
  3. 一般情况下子查询结果集不会大的离谱,所以会为它建立基于内存的使用 Memory 存储引擎的临时表,而且会为该表建立哈希索引。
  4. 如果子查询的结果集非常大,超过了系统变量 tmp_table_size 或者 max_heap_table_size ,临时表会转而
    使用基于磁盘的存储引擎来保存结果集中的记录,索引类型也对应转变为 B+ 树索引。
    这个将子查询结果集中的记录保存到临时表的过程称之为 物化。

物化表转连接

当我们把子查询进行物化之后,假设子查询物化表的名称为 materialized_table ,该物化表存储的子查询结果集的列为 m_val ,那么这个查询其实可以从下边两种角度来看待:

SELECT * FROM s1
WHERE key1 IN (SELECT common_field FROM s2 WHERE key3 = ‘a');

从表 s1 的角度来看待,整个查询的意思其实是:对于 s1 表中的每条记录来说,如果该记录的 key1 列的值

在子查询对应的物化表中,则该记录会被加入最终的结果集。画个图表示一下就是这样:

从子查询物化表的角度来看待,整个查询的意思其实是:对于子查询物化表的每个值来说,如果能在 s1 表
中找到对应的 key1 列的值与该值相等的记录,那么就把这些记录加入到最终的结果集。

也就是说其实上边的查询就相当于表 s1 和子查询物化表 materialized_table 进行内连接:

SELECT s1.* FROM s1 INNER JOIN materialized_table ON key1 = m_val;

如果使用 s1 表作为驱动表的话,总查询成本由下边几个部分组成:

  1. 物化子查询时需要的成本
  2. 扫描 s1 表时的成本
  3. s1表中的记录数量 × 通过 m_val = xxx 对 materialized_table 表进行单表访问的成本(物化表中的记录是不重复的,并且为物化表中的列建立了索引,所以这个步骤显然是非常快的)。

如果使用 materialized_table 表作为驱动表的话,总查询成本由下边几个部分组成:

  1. 物化子查询时需要的成本
  2. 扫描物化表时的成本
  3. 物化表中的记录数量 × 通过 key1 = xxx 对 s1 表进行单表访问的成本

总结

到此这篇关于Mysql查询优化之IN子查询优化方法的文章就介绍到这了,更多相关Mysql IN子查询优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • windows10+mysql8.0.11zip安装教程详解

    windows10+mysql8.0.11zip安装教程详解

    这篇文章主要介绍了windows10+mysql8.0.11zip安装教程详解,本文给大家介绍的非常详细,具有参考借鉴价值,需要的朋友可以参考下
    2018-05-05
  • 本地windows安装两个mysql服务器,配置主从同步

    本地windows安装两个mysql服务器,配置主从同步

    大型网站为了缓解大量的并发访问,除了在网站实现分布式负载均衡,还会搭建服务器mysql集群技术,来分担主数据库的压力。在本地电脑能实现这样的技术吗,本地windows安装两个mysql服务器,配置主从同步也是可以实现的,快来跟着教程测试一下吧。
    2022-12-12
  • 浅谈MySQL临时表与派生表

    浅谈MySQL临时表与派生表

    MySQL在处理请求的某些场景中,服务器创建内部临时表。即表以MEMORY引擎在内存中处理,或以MyISAM引擎储存在磁盘上处理.如果表过大,服务器可能会把内存中的临时表转存在磁盘上。
    2017-02-02
  • mysql批量执行sql文件的方法

    mysql批量执行sql文件的方法

    下面小编就为大家带来一篇mysql批量执行sql文件的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编 过来看看吧
    2016-10-10
  • mysql数据插入覆盖和时间戳的问题及解决

    mysql数据插入覆盖和时间戳的问题及解决

    这篇文章主要介绍了mysql数据插入覆盖和时间戳的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 将MySQL数据库移植为PostgreSQL

    将MySQL数据库移植为PostgreSQL

    PostgreSQL 作为功能最强劲的开源 OO 数据库,仿佛一直不为国内用户所熟识。而我个人也仅是因为工作的缘故接触到这款超经典的数据库,并深为之折服。
    2009-07-07
  • 关于MYSQL 你需要知道的数据类型和操作数据表

    关于MYSQL 你需要知道的数据类型和操作数据表

    这篇文章主要介绍了关于MYSQL中数据类型的知识和操作数据表的方法,文中讲解非常详细供大家参考学习,感兴趣的朋友可以了解下
    2020-06-06
  • MySQL Workbench的使用方法(图文)

    MySQL Workbench的使用方法(图文)

    这篇文章主要介绍了MySQL Workbench的使用方法(图文) ,需要的朋友可以参考下
    2016-02-02
  • MySQL 查看事务和锁情况的常用语句分享

    MySQL 查看事务和锁情况的常用语句分享

    这篇文章主要介绍了MySQL 查看事务和锁情况的常用语句分享,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • MySQL缓存的查询和清除命令使用详解

    MySQL缓存的查询和清除命令使用详解

    这篇文章主要介绍了MySQL缓存的查询和清除命令使用详解,对于一些不常改变数据且有大量相同sql查询的表,查询缓存会显得比较有用一些,需要的朋友可以参考下
    2015-12-12

最新评论