在某系统中想使用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. gevent-协程用法

    文章介绍了一种采用循环的方式生产协程列表,并可以向协程函数传递参数... # 协程引用import gevent from gevent import monkey, pool monkey.patc ...

  2. CAM(Content Addressable Memory)介绍

    CAM是一种特殊的存储器.所谓CAM,即内容寻址存储器.CAM存储器在其每个存储单元都包含了一个内嵌的比较逻辑,写入CAM的数据会和其内部存储的每一个数据进行比较,并返回与端口数据相同的所有内部数据的 ...

  3. day052-53 django框架

    一.MVC和MTV模型 这就是web开发中的一种思维模式或者说一套理念,MTV也是基于MVC发展出来的,本质相同,都是使各组件保持松耦合 MVC  把web应用分为模型(model),控制器(cont ...

  4. ZZW_shell脚本中的调用MYSQL传参及注意的问题

    [oracle@ip9140 db_pcc]$ cat zzw_cc.sh #!/bin/bash z_user='pcc_csuser22'z_pass='pcc_csuser22'z_db='db ...

  5. Java框架部分---面试题

    说说Spring? Spring的核心是控制反转.依赖注入,Aop(面向切面)相当于把每个bean与bean之间的关系交给第 三方容器进行管理. 说SpringIOC.SpringAOP? Sprin ...

  6. httpd-2.4安装配置

    接收请求的类型: 并发访问响应模型: 单进程I/O模型:启动一个进程处理用户请求,这意味着一次只能处理一个请求,多个请求被串行响应: 多进程I/O模型:由父进程并行启动多个子进程,每个子进程响应一个请 ...

  7. Android开发 ---xml构建选项菜单、上下文菜单(长按显示菜单)、发通知、发送下载通知

    1.activity_main.xml 描述: 定义了一个TextView和三个按钮 <?xml version="1.0" encoding="utf-8&quo ...

  8. C++内存管理-new,delete,new[],placement new的简单使用

    技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 首先,我们先看一下C++应用程序,使用memory的途径如下图所示 C++应用程序中申请内存基于分配器的实现(std::allo ...

  9. 不得不补:PHP的JSON, SQL

    不管怎么说,还是得感谢慕课网,提供了很多免费的视频教学. 学习自: https://www.imooc.com/view/68 前端页面: <!DOCTYPE html> <html ...

  10. java_opts 参数与JVM内存调优

    Linux修改catalina.sh文件 如: JAVA_OPTS=”-server -Dfile.encoding=UTF-8 -Xms=512m -Xmx1024m -XX:PermSize=12 ...