Mysql查询优化之IN子查询优化方法详解
作者:云深n不知处 发布时间:2024-01-16 11:38:07
物化表
首先提出一个不相关的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 … ,这样性能耗费可就多了。
所以提出一个解决方案:不直接将不相关子查询的结果集当作外层查询的参数,而是将该结果集写入一个临时表里。
临时表的特性:
该临时表的列就是子查询结果集中的列。
写入临时表的记录会被去重。
一般情况下子查询结果集不会大的离谱,所以会为它建立基于内存的使用 Memory 存储引擎的临时表,而且会为该表建立哈希索引。
如果子查询的结果集非常大,超过了系统变量 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 表作为驱动表的话,总查询成本由下边几个部分组成:
物化子查询时需要的成本
扫描 s1 表时的成本
s1表中的记录数量 × 通过 m_val = xxx 对 materialized_table 表进行单表访问的成本(物化表中的记录是不重复的,并且为物化表中的列建立了索引,所以这个步骤显然是非常快的)。
如果使用 materialized_table 表作为驱动表的话,总查询成本由下边几个部分组成:
物化子查询时需要的成本
扫描物化表时的成本
物化表中的记录数量 × 通过 key1 = xxx 对 s1 表进行单表访问的成本
来源:https://blog.csdn.net/qq_50629351/article/details/128926613


猜你喜欢
- python按指定行数把大文件进行拆分如图大文件有7000多万行,大小为16G需要拆分成多个200万行的小文件代码如下:# -*- codi
- 前言:jieba是优秀的中文分词第三方库,由于中文文本之间每个汉字都是连续书写的,我们需要通过特定的手段来获得其中的每个词组,这种手段叫做分
- 本文实例为大家分享了40行Python代码实现计算器功能,供大家参考,具体内容如下偶尔用脚本写点东西也是不错的。效果图代码from tkin
- 本文实例讲述了codeigniter发送邮件并打印调试信息的方法。分享给大家供大家参考。具体如下:这里的codeigniter代码实现发送邮
- 如下所示:<?phpnamespace helpers;class OpensslRSA{ //echo $private_key 私
- OCR简介OCR,即Optical Character Recognition,光学字符识别,是指通过扫描字符,然后通过其形状将其翻译成电子
- 因一些特殊需求需要以参数的形式获取字典 * 定的值,网上搜了一下并没有特别好的实现(并没有太认真去找~),所以自己实现了一个,以供大家参考:)
- 废话不多说了,直接上代码吧!import numpy as nparray = np.array([0, 0])for i in range
- 本文实例讲述了Python实现的合并两个有序数组算法。分享给大家供大家参考,具体如下:思路按位循环比较两个数组,较小元素的放入新数组,下标加
- 首先是不知道怎么忽然mysql用命令行,workbench都登录不了,都提示'Access denied for user '
- matplotlib简介如果你在大学里参加过数学建模竞赛或者是用过MATLAB的话,相比会对这一款软件中的画图功能印象深刻。MATLAB可以
- 方法一 :使用常规的思路def transpose(M): # 初始化转置后的矩阵 result = [] &nbs
- DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行
- 代码如下: 在ie下,貌似要改安全设置中的【对为标记为可安全执行脚本的ActiveX空间初始化并执行】那项 <html> <
- 由于一些不可预测的因素,必须使用python2.7进行开发,所以研究了一下怎么在Anaconda3下建立2.7的开发环境,发现十分方便,在此
- Python import的搜索路径import的搜索路径为:搜索「内置模块」(built-in module)搜索 sys.path 中的
- 我的主要思路是:Excel -> Html -> Image代码如下:# -*- coding:utf-8 -*-__autho
- 一、下载下载链接:https://www.anaconda.com/二、安装过程安装过程,所有都选默认项目。三、系统环境配置路径:此电脑-属
- 引言在深度学习的实际应用中,我们经常用到的原始数据是图片文件,如jpg,jpeg,png,tif等格式的,而且有可能图片的大小还不一致。而在
- 本文实例为大家分享了python实现推箱子游戏的具体代码,供大家参考,具体内容如下题目描述:最短路径为:uurrDDDDuuuulldRur