WHY?

  • IN 和 NOT IN 是比较常用的关键字,为什么要尽量避免呢?

1、效率低

  • 项目中遇到这么个情况:
  • t1表 和 t2表  都是150w条数据,600M的样子,都不算大。
  • 但是这样一句查询 
    select * from t1 where phone not in (select phone from t2)
  • 直接就把我跑傻了。。。十几分钟,检查了一下  phone在两个表都建了索引,字段类型也是一样的。原来not in 是不能命中索引的。。。。
  • 改成 NOT EXISTS 之后查询 20s ,效率真的差好多。
    1.  
      select * from t1
    2.  
      where not EXISTS (select phone from t2 where t1.phone =t2.phone)
     

2、容易出现问题,或查询结果有误 (不能更严重的缺点)

  • 以 IN 为例。建两个表:test1 和 test2
    1.  
      create table test1 (id1 int)
    2.  
      create table test2 (id2 int)
    3.  
       
    4.  
      insert into test1 (id1) values (1),(2),(3)
    5.  
      insert into test2 (id2) values (1),(2)
     
  • 我想要查询,在test2中存在的  test1中的id 。使用IN的一般写法是:
    1.  
      select id1 from test1
    2.  
      where id1 in (select id2 from test2)
 
  • 结果是: OK 木有问题!
  • 但是如果我一时手滑,写成了:
    1.  
      select id1 from test1
    2.  
      where id1 in (select id1 from test2)
 
  • 不小心把id2写成id1了 ,会怎么样呢?
  • 结果是: EXCUSE ME! 为什么不报错? 
    1.  
      单独查询 select id1 from test2 是一定会报错: 消息 207,级别 16,状态 1,第 11 行 列名 'id1' 无效。
    2.  
      然而使用了IN的子查询就是这么敷衍,直接查出 1 2 3
  • 这仅仅是容易出错的情况,自己不写错还没啥事儿,下面来看一下 NOT IN 直接查出错误结果的情况:
  • 给test2插入一个空值:
     
insert into test2 (id2) values (NULL)
  • 我想要查询,在test2中不存在的  test1中的id 。
    1.  
      select id1 from test1
    2.  
      where id1 not in (select id2 from test2)
  • 结果是:空白! 显然这个结果不是我们想要的。我们想要3。为什么会这样呢?
  • 原因是:NULL不等于任何非空的值啊!如果id2只有1和2, 那么3<>1 且 3<>2 所以3输出了,但是 id2包含空值,那么 3也不等于NULL 所以它不会输出。

  1. (跑题一句:建表的时候最好不要允许含空值,否则问题多多。)
 

HOW?

1、用 EXISTS 或 NOT EXISTS 代替

  1.  
    select * from test1
  2.  
    where EXISTS (select * from test2 where id2 = id1 )
  3.  
    select * FROM test1
  4.  
    where NOT EXISTS (select * from test2 where id2 = id1 )

2、用JOIN 代替

  1.  
    select id1 from test1
  2.  
    INNER JOIN test2 ON id2 = id1
  3.  
    select id1 from test1
  4.  
    LEFT JOIN test2 ON id2 = id1
  5.  
    where id2 IS NULL

妥妥的没有问题了!

  • PS:那我们死活都不能用 IN 和 NOT IN 了么?并没有,一位大神曾经说过,如果是确定且有限的集合时,可以使用。如 IN (0,1,2)。

SQL优化 - 避免使用 IN 和 NOT IN的更多相关文章

  1. SQL优化案例—— RowNumber分页

    将业务语句翻译成SQL语句不仅是一门技术,还是一门艺术. 下面拿我们程序开发工程师最常用的ROW_NUMBER()分页作为一个典型案例来说明. 先来看看我们最常见的分页的样子: WITH CTE AS ...

  2. sql 优化

    1.选择最有效率的表名顺序(只在基于规则的优化器中有效): oracle的解析器按照从右到左的顺序处理 from 子句中的表名,from子句中写在最后的表(基础表driving table)将被最先处 ...

  3. SQL 优化总结

    SQL 优化总结 (一)SQL Server 关键的内置表.视图 1. sysobjects         SELECT name as '函数名称',xtype as XType  FROM  s ...

  4. (转)SQL 优化原则

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  5. sql优化阶段性总结以及反思

    Sql优化思路阶段性心得: 这段时间的优化做了好几个案例,其实有很多的类似点,都是好几张大表的相互连接,然后执行长达好几个小时,甚至都跑不出来. 自己差不多的思路就是Parallel full tab ...

  6. mysql sql优化实例

    mysql sql优化实例 优化前: pt-query-degist分析结果: # Query 3: 0.00 QPS, 0.00x concurrency, ID 0xDC6E62FA021C85B ...

  7. SQL优化技巧

    我们开发的大部分软件,其基本业务流程都是:采集数据→将数据存储到数据库中→根据业务需求查询相应数据→对数据进行处理→传给前台展示.对整个流程进行分析,可以发现软件大部分的操作时间消耗都花在了数据库相关 ...

  8. ORACLE常用SQL优化hint语句

    在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量, ...

  9. SQL优化有偿服务

    本人目前经营MySQL数据库的SQL优化服务,100块钱一条.具体操作模式 其中第一条,可以通过在微信朋友圈转发链接中的信息(http://www.yougemysqldba.com/discuz/v ...

  10. 【MySQL】SQL优化系列之 in与range 查询

    首先我们来说下in()这种方式的查询 在<高性能MySQL>里面提及用in这种方式可以有效的替代一定的range查询,提升查询效率,因为在一条索引里面,range字段后面的部分是不生效的. ...

随机推荐

  1. c#day04从控制台获取一个字符

    class EnumStruct { //定义QQ的状态枚举 Qme QnLine OffLine Leave Busy //提示用户现在一个状态 然后接收 ,并将用户输入转换成枚举类 enum Qs ...

  2. XrmToolBox 连接

  3. webpack 配置案例for angular babel

    1.dev.js: const webpack = require('webpack'); const webpackUglifyJsPlugin = require('webpack-uglify- ...

  4. C Mysql API连接Mysql

    最近都在查看MYsql C API文档,也遇到了很多问题,下面来简单的做一个总结. mysql多线程问题 mysql多线程处理不好,经常会发生coredump,见使用Mysql出core一文. 单线程 ...

  5. 08 bash特性--shell脚本编程入门

    shell脚本编程入门 编程语言介绍 编程语言分为:机械语言.汇编语言和高级语言: 计算机能识别的语言为机械语言,而人类能学习的并且能够方便掌握的为高级语言,所以,我们所编写的程序就要通过编译来转换成 ...

  6. Linux TCP/IP调优-Linux内核参数注释

    固定文件的内核参数 下列文件所在目录: /proc/sys/net/ipv4/ 名称 默认值 建议值 描述 tcpsyn_retries 5 1 对于一个新建连接,内核要发送多少个SYN连接请求才决定 ...

  7. build.gradle 中compileSdkVersion,minSdkVersion,targetSdkVersion,buildToolsVersion的意思

    compileSdkVersion: 编译版本:compileSdkVersion告诉gradle使用哪个版本AndroidSDK编译你的应用: minSdkVersion: 最低SDK版本:他代表的 ...

  8. bool操作

    基本类型转换的问题 bool类型没有操作. 类型转换 结论一: 想把xxx转化成yy类型. yy(xxx) 结论二: 能够表示False的数据: 0, "", [], {}, se ...

  9. django之前-----web应用与框架

    一web应用 web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件.应用程序有两种模式C/S.B/S. 下面来看一个简 ...

  10. js数据类型 --运算符

    基本数据类型: number: var a=1; string: var str='123'; boolean: var b1=false; null:var c1=null; //打印结果为 obj ...