Sql语句中IN和exists的区别及应用

not in 和not exists

  如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快。

 

in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。一直以来认为exists比in效率高的说法是不准确的。

in 和 exists的区别: 如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in;反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。

其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键)

如果是exists,那么以外层表为驱动表,先查询主查询再将结果和内表中的子查询进行对比。详细执行步骤如下:使用exists关键字进行查询的时候,首先,我们先查询的不是子查询的内容,而是查我们的主查询的表。然后,根据表的每一条记录,再去子查询的内表中依次去判断where后面的条件是否成立:如果成立则返回true不成立则返回false。如果返回的是true的话,则该行结果保留,如果返回的是false的话,则删除该行,最后将得到的结果返回。

如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了 ,另外IN时不对NULL进行处理。详细执行步骤如下:首先,在数据库内部将先进行查询子查询。然后,将子查询到的结果和原有的外表做一个笛卡尔积。最后,再根据IN设置的条件,将结果进行筛选后返回。

下面以实际sql语句来讲解下子查询、主查询 以及内表、外表

select * from A where cc in (select cc from B)
select * from A where exists(select cc from B where cc=A.cc)

从查询结果都是A表中的字段信息来看select * from A这个查询就是主查询,从括号的角度理解A表就是外表

B表中查询出的字段是用作条件判断的,可以理解成子查询,括号中的B表也就是内表

 

实际速度测试

一般来说子查询中表数据小的使用IN,子查询中表数据大的使用EXISTS,但是关于速度的解释一直具有争议,因此亲自测试一番,看看哪个性能好。

准备两张表,user表中4096条数据作主查询,order表中3条数据作子查询,其中2条数据和user表有关联

测试sql语句以及测试结果如下所示:

SELECT * FROM `user` WHERE  `user`.id IN ( SELECT `order`.user_id FROM `order`)
SELECT `user`.* FROM `user` WHERE EXISTS ( SELECT `order`.user_id FROM `order` WHERE 
 `user`.id = `order`.user_id )

结论:

子查询中order表数据小,使用IN的时间比使用EXISTS的要短,速度更快一些。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值