在某系统中想使用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. Unity3d外包-就找北京动点软件

    承接Unity3d体感企业项目.游戏项目外包 北京公司.专业团队,成员为专业Unity3d产品公司一线开发人员,有大型产品开发经验: 提供优质的售后服务,保证产品质量,轻量级产品可以提供规范清晰的源代 ...

  2. Django2.1.5使用xadmin打造适合国人的后台管理系统

    python做web开发的话,flask.django是比较火的框架了,django是一个比较大的框架,也是一个快速开发利器.但是,django自带的后台admin不太好看,也不太符合我们国人的习惯, ...

  3. Android 回退键监听

    回退键(back)监听:方法1:回调方法onBackPressed String LOG_TAG="TAG";  @Override    public void onBackPr ...

  4. guxh的python笔记二:函数基础

    1,函数的参数 1.1,查看函数的参数类型 def run(a, *args, b, **kwargs): return a + b 可以通过如下方式查看参数类型: import inspect k ...

  5. js之原型,原型链

    1.原型是什么?    在构造函数创建出来的时候,系统会默认的创建并关联一个对象,这个对象就是原型,原型对象默认是空对象    默认的原型对象中会有一个属性constructor指向该构造函数  原型 ...

  6. Ansible 小手册系列 十四(条件判断和循环)

    条件判断 When 语句 在when 后面使用Jinja2 表达式,结果为True则执行任务. tasks: - name: "shut down Debian flavored syste ...

  7. 实践:搭建基于Load Balancer的MySql Cluster

    服务器规划: 整套系统全部在rhel5u1 server 64位版本下,由基于xen的虚拟机搭建,其中集群管理节点*2.SQL节点*2.数据节点*4.Web服务节点*2组成,其中数据节点做成2个组,每 ...

  8. coursera-斯坦福-机器学习-吴恩达-笔记week3

    1 逻辑回归 1. classification 分类 eg:垃圾邮件分类.交易是否是欺诈.肿瘤类别.分类的结果是离散值. 2. sigmoid函数 使用线性方法来判断分类问题,会出现上图中的问题,需 ...

  9. codeblock不能调试

    问题:codeblock  不能调试,如下图: 解决方法: 首先,项目的保存路径不能是中文路径. 其次,必须创建工程. 最后,build选项里select target选成debug codebloc ...

  10. 关于空指针NULL、野指针、通用指针 (转)

    reference:https://www.cnblogs.com/losesea/archive/2012/11/16/2772590.html 首先说一下什么是指针,只要明白了指针的含义,你就明白 ...