聚合国内IT技术精华文章,分享IT技术精华,帮助IT从业人士成长

为什么要尽量避免使用IN和NOT IN?

2022-03-15 10:48 浏览: 1388 次 我要评论(0 条) 字号:

「 关注“石杉的架构笔记”,大厂架构经验倾囊相授 

 儒猿技术团队最新出品
《大型企业级分布式订单系统项目实战》

(点击查看详情)

文章来源:http://u6.gg/k5xdn


对数据了解的同学,一定对于 IN 和 NOT IN 无比的熟悉,今天来说说既然那么常用,但是为什么要尽量避免使用呢?

WHY?


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


| 效率低

项目中遇到这么个情况:t1表 和 t2表  都是150w条数据,600M的样子,都不算大。


但是这样一句查询,直接就把我跑傻了......
select * from t1 where phone not in (select phone from t2)


十几分钟,检查了一下  phone 在两个表都建了索引,字段类型也是一样的。原来 not in 是不能命中索引的!


改成 NOT EXISTS 之后查询 20s ,效率真的差好多。
select * from t1 
where  not  EXISTS (select phone from t2  where t1.phone =t2.phone)


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

以 IN 为例,建两个表:test1 和 test2。
create table test1 (id1 int)
create table test2 (id2 int)

insert into test1 (id1) values (1),(2),(3)
insert into test2 (id2) values (1),(2)


我想要查询,在 test2 中存在的  test1 中的 id 。使用 IN 的一般写法是:
select id1 from test1 
where id1 in (select id2 from test2)


结果是:
OK 木有问题!但是如果我一时手滑,写成了:
select id1 from test1 
where id1 in (select id1 from test2)


不小心把 id2 写成 id1 了 ,会怎么样呢?结果是:

EXCUSE ME!为什么不报错?


单独查询 select id1 from test2 是一定会报错:消息 207,级别 16,状态 1,第 11 行 列名 'id1' 无效。然而使用了 IN 的子查询就是这么敷衍,直接查出 1 2 3。


这仅仅是容易出错的情况,自己不写错还没啥事儿,下面来看一下 NOT IN 直接查出错误结果的情况。


给 test2 插入一个空值:
insert into test2 (id2) values (NULL)


我想要查询,在 test2 中不存在的 test1 中的 id 。
select id1 from test1 
where id1 not in (select id2 from test2)


结果是:

空白!显然这个结果不是我们想要的。我们想要 3。为什么会这样呢?


原因是:NULL 不等于任何非空的值啊!如果 id2 只有 1 和 2, 那么 3<>1 且 3<>2,所以 3 输出了,但是 id2 包含空值,那么 3 也不等于 NULL,所以它不会输出。


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


HOW?


EXISTS 或 NOT EXISTS 代替:

select *  from test1 
   where EXISTS (select * from test2  where id2 = id1 )

select *  FROM test1  
 where NOT EXISTS (select * from test2  where id2 = id1 )


用 JOIN 代替:

 select id1 from test1 
   INNER JOIN test2 ON id2 = id1 

 select id1 from test1 
   LEFT JOIN test2 ON id2 = id1 
   where id2 IS NULL


妥妥的没有问题了!


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


-------------  END  -------------

更多 Spring Cloud Alibaba 学习资

迎扫码加群领取

点个在看你最好看



网友评论已有0条评论, 我也要评论

发表评论

*

* (保密)

Ctrl+Enter 快捷回复