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. [UE4]非常实用的SizeBox控件

    Desired:表示以期望的实际尺寸显示视图. SizeBox最好作为Child Widget的根节点.(如果SizeBox的父节点是Canvas Panel,SizeBox会变成可拉伸,ChildL ...

  2. [UE4]给Widget增加参数,Pre Construct和Construct的区别

    使用Pre Construct事件可以在编辑器中实时显示出选择的背景图片. 如果使用的是“Construct”事件则只能在游戏运行时把图片显示出来.

  3. [UE4]蓝图替换节点、引用快捷方式

  4. tensorFlow 三种启动图的用法

    tf.Session(),tf.InteractivesSession(),tf.train.Supervisor().managed_session()  用法的区别: tf.Session() 构 ...

  5. SAS 数值转日期

    DATA _NULL_;FORMAT A YYMMDDN8.;B=PUT(20180101,$8.);A=INPUT(B,YYMMDD8.);PUT B= A=;RUN; 输出:47   DATA _ ...

  6. Ext.NET Combobox实现数据源静态配置

    背景 项目中使用增值税税率, 需求原本是统一的指定税率, 譬如3% 5% 等固定的. 随着业务增加, 发现不同业务有不同的税率, 一会加一个, 一下要改很多个界面. 就想着放到统一的地方. 技术背景 ...

  7. Jupyter配置步骤

    Jupyter是基于浏览器的可交互式开发工具,在数据科学界非常受欢迎,它功能齐全,使用方便,是一款数据分析和建模挖掘的利器. 本文简介Jupyter的配置和使用过程 一.修改添加国内镜像 通常我会先安 ...

  8. 第10章 网络安全(3)_安全套接字层SSL

    4. 安全套接字层 4.1 安全套接字层(SSL)和传输层安全(TLS) (1)SSL/TLS提供的安全服务 ①SSL服务器鉴别,允许用户证实服务器的身份.支持SSL的客户端通过验证来自服务器的证书, ...

  9. gulp 编译es6 react 教程 案例 配置

    1.gulp基本配置: var gulp = require('gulp'), watch = require('gulp-watch'), babel = require('gulp-babel') ...

  10. 关于chrome控制台警告:Synchronous XMLHttpRequest on the main thread

    Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to th ...