在某系统中想使用NOT IN子查询进行数据过滤,SQL为:

SELECT * FROM TB001 AS T1
WHERE T1.update_time<DATE_ADD(NOW(),INTERVAL -90 DAY)
AND T1.BATCH_NO NOT IN(SELECT BATCH_NO FROM TB002 AS T2 )
AND T1.OPT_STATUS=2 AND T1.BATCH_TYPE=10
LIMIT 1000

上面SQL执行时间未6.84秒,相关表数据量为:
表TB001:507716
表TB002:11266065

为验证NOT IN 子查询对查询的影响,移除NOT IN子查询后,SQL调整为:

SELECT * FROM TB001 AS T1
WHERE T1.update_time<DATE_ADD(NOW(),INTERVAL -90 DAY)
AND T1.OPT_STATUS=2 AND T1.BATCH_TYPE=10
LIMIT 1000

SQL执行时间未0.15秒

将上面NOT IN语句转换为程序伪代码:

## 设置limit 返回行数
int limit_row_count=1000
## 使用match_row_list存放满足的记录
match_row_list=[]
## 按照update_time上索引遍历满足update_time条件的记录
## 单次操作消耗约为6,一次按索引键读取+一次按主键读取
for row_item in TB001 where update_time<DATE_ADD(NOW(),INTERVAL -90 DAY):
## 按照其他条件过滤记录
if row_item .OPT_STATUS=2 AND row_item .BATCH_TYPE=10:
## 按照子查询过滤记录
## 单次操作约为3或4,一次按索引键读取
if not exists (SELECT BATCH_NO FROM TB002 where BATCH_NO=row_item.BATCH_NO )
## 将满足子查询的记录放到list中
match_row_list.append(row_item)
## 满足limit行数后返回
if match_row_list.length()==limit_row_count:
retrun match_row_list

该SQL执行效率取决于3点:
1、满足update_time条件的记录总数(TN)
2、满足update_time条件的记录存满足NOT IN子查询的概率(PT)
3、查询需要返回的数据行数即LIMIT数量(LN)
4、对于NOT IN子查询内部,查询仅需要找到第一条满足条件的记录即可返回,子表TB002的数据量与查询时间没有明显关系

假设每遍历一条满足update_time条件的记录的操作消耗为10,查询消耗=10*Min((LN/PT),TN),:
1、最坏情况下,LN/PT的值远大于TN时或TN*PT的值小于LN时,查询需要遍历所有满足update_time条件的记录,即查询消耗最高为=10*TN
2、最佳情况下,当PT概率足够高无限接近于1时,查询遍历LN条数据即可跳出循环,查询最低消耗为=10*LN
3、普通场景下,需要返回的数量LN小于满足NOT IN条件的数量(TN*PT),查询消耗=10*LN/PT,查询消耗与PT成反比.

数据分布对查询性能影响:
在很多业务场景下,记录满足NOT IN子查询的概率并不是均匀的,以网站注册用户为例,并不是所有用户的购买商品概率都相同,最新注册用户购买商品的概率会远高于两年前注册用户。

扩展知识:
1、在按照索引查找记录(LIMIT 1或EXIST操作)时,查询效率与索引层级相关,受表数据量影响较小,相同表结构下,100万数据量索引层级可能为4,1000万数据量的索引层级也可能为4,此时访问100万数据量表的消耗和访问1000万数据量表的消耗相同和接近。
2、当SQL语句在数据库上执行时,查询优化器会按照统计信息来评估生成执行计划,MySQL内部会按照某些公式对SQL语句进行转换,如IN操作可能会被转换成EXIST操作,也可能依旧为IN操作,这也是结构化查询语言与编译语言的重要区别。

MySQL Execution Plan--NOT IN查询的更多相关文章

  1. sql server 执行计划(execution plan)介绍

    大纲:目的介绍sql server 中执行计划的大致使用,当遇到查询性能瓶颈时,可以发挥用处,而且带有比较详细的学习文档和计划,阅读者可以按照我计划进行,从而达到对执行计划一个比较系统的学习. 什么是 ...

  2. Execution Plan 执行计划介绍

    后面的练习中需要下载 Demo 数据库, 有很多不同的版本, 可以根据个人需要下载.  下载地址 -http://msftdbprodsamples.codeplex.com/ 1. 什么是执行计划 ...

  3. MySQL 5.5开启慢查询功能

    vim /etc/my.cnf [mysqld] slow-query-log = on # 开启慢查询功能 slow_query_log_file = /usr/local/mysql/data/s ...

  4. 提高MYSQL百万条数据的查询速度

    提高MYSQL百万条数据的查询速度 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 nul ...

  5. MySQL:动态开启慢查询日志(Slow Query Log)

    前言 在开发中,高效能的程序 也包括 高效能的查询,所以优化SQL也是程序员必要技能之一.要优化就必须要有慢日志记录才可以知道哪些查询慢,然后反向去修改 慢日志设置方式 写入文件 写入数据库 实践操作 ...

  6. Oracle SQL explain/execution Plan

    From http://blog.csdn.net/wujiandao/article/details/6621073 1. Four ways to get execution plan(anyti ...

  7. Oracle、MySql、SQLServer数据分页查询

    看过此博文后Oracle.MySql.SQLServer 数据分页查询,在根据公司的RegionRes表格做出了 SQLserver的分页查询语句: 别名.字段 FROM( SELECT row_nu ...

  8. 高性能MySQL笔记 第6章 查询性能优化

    6.1 为什么查询速度会慢   查询的生命周期大致可按照顺序来看:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回结果给客户端.其中“执行”可以认为是整个生命周期中最重要的阶段. ...

  9. Oracle、MySql、SQLServer 数据分页查询

    最近简单的对oracle,mysql,sqlserver2005的数据分页查询作了研究,把各自的查询的语句贴出来供大家学习..... (一). mysql的分页查询 mysql的分页查询是最简单的,借 ...

  10. [mysql] mysql 5.6.X 慢查询日志

    慢查询日志 一篇好文章,学习保存.... 打开慢查询日志 慢查询日志,顾名思义就是记录执行比较慢查询的日志. 查看是否开启慢查询日志: show variables like '%slow%'; 打开 ...

随机推荐

  1. 【洛谷p1605】迷宫

    (还记得我昨天大概没人看到的博客(我删辽)吗qwq,2019.4.14下午交的qwq 那篇博客大致内容就是:我提交楼上这道题,交了好久好久好久好久 现在我告诉你,那次评测还N/A着呢qwq) tqlq ...

  2. laravel command调用方法命令

  3. .net获取程序根目录

    获取程序的根目录: var path = HttpRuntime.AppDomainAppPath;

  4. SSH框架学习摸索记

    Unable to load configuration. - bean - jar:file:/E:/tomcat-7.0.11/webapps/struts/WEB-INF/lib/struts ...

  5. Starting MySQL....The server quit without updating PID file[失败]/lib/mysql/ip12189.pid). 错误一例

    [root@ip12189 etc]# service mysqld startStarting MySQL....The server quit without updating PID file[ ...

  6. python命名空间与作用域

    python命名空间与作用域   命名空间是名称与对象之间的关系,可以将命名空间看做是字典,其中的键是名称,值是对象. 命名空间不共享名称. 在命名空间中的名称能将任何python对象作为值,在不同的 ...

  7. vue 自定义组件使用v-model

    <input v-model="something"> v-model指令其实是下面的语法糖包装而成: <input :value="something ...

  8. C++解析十-数据封装

    数据封装 所有的 C++ 程序都有以下两个基本要素: 程序语句(代码):这是程序中执行动作的部分,它们被称为函数. 程序数据:数据是程序的信息,会受到程序函数的影响.封装是面向对象编程中把数据和操作数 ...

  9. 诡异的bug!!

    在我些项目的时候,命名从来没有用过 font 元素,但是打开 Chrome 浏览器查看元素时,总是 font 元素???而且写的 <span class= "xxx"> ...

  10. Debian/Ubuntu/Deepin下AndroidStudio2/3打开AVD模拟器无反应

    Debian系AS无法启动模拟器 问题描述 早在半年前将开发环境从windows迁移到了Linux:当时用的是Debian系统,也是在安装完成AndroidStudio之后无法开启模拟器,也没出现什么 ...