在某系统中想使用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. antd Select进阶功能 动态更新、函数防抖

    一.动态更新Options Antd Select自带的搜索功能很多时候需要结合后端的接口,输入一个关键字的时候会自动更新选择器的选项. 下面列一些注意点 基础实现 选择器选项必须和每次更新的数据挂钩 ...

  2. Struts2 环境配置

    1.下载struts2开发包 2.将apps中的 Struts-blank.war 解压,里面的 lib 中就是所需jar包 3.新建一个web project项目,将jar包导入复制粘贴到lib中 ...

  3. Java ceil() 方法

    语法: double ceil(double d) double ceil(float f) 参数 double 或 float 的原生数据类型. 返回值 返回 double 类型,返回值大于或等于给 ...

  4. 雷林鹏分享:jQuery EasyUI 数据网格 - 创建属性网格

    jQuery EasyUI 数据网格 - 创建属性网格 属性网格(property grid)带有一个内置的 expand(展开)/collapse(合并) 按钮,可以简单地为行分组.您可以简单地创建 ...

  5. Python使用ldap3认证

    一.安装ldap3模块(python版本为python3以上,Django=1.11.8)pip install ldap3 二.相关代码 from ldap3 import Server, Conn ...

  6. hdoj5754

    题意:略 国王和骑士用记忆搜索,注意骑士的移动是x-2,y-1或x-1,y-2.车是NIM博弈,后是威佐夫博弈.注意威佐夫博弈中两堆石子有大小之分,而输入不一定小在前. #include <io ...

  7. 『PyTorch』第五弹_深入理解Tensor对象_中下:数学计算以及numpy比较_&_广播原理简介

    一.简单数学操作 1.逐元素操作 t.clamp(a,min=2,max=4)近似于tf.clip_by_value(A, min, max),修剪值域. a = t.arange(0,6).view ...

  8. spring boot的热加载(hotswap)

    官网上是叫hotswap,有人翻译成热部署,有人翻译成热加载 个人倾向于使用热加载在这个词,和谷歌翻译的热插拔相似. 关于个人理解 http://www.cnblogs.com/ptqueen/p/8 ...

  9. Centos 7 搭建DNS笔记

    bindind的程序包 bind-libs:被bind和bind-utils包中的程序共同用到的库文件: bind-utils:bind客户端程序集:提供了,dig , host, nslookup等 ...

  10. 使用VBA,优化处理Excel表格

    前言 上周末,XX给我抱怨:因为计算绩效奖金,把2个人的工资发错了,还被扣了500元.问的缘由得知,她每个月要处理十来个excel表格,每次都要手动修改里面的值,如果修改了一处,其他地方也要修改,然后 ...