前言

在面试谈到sql优化的一些经验时,有些面试者会回答:写sql时,最好用exists来代替in,因为in不走索引,所以用exists的sql性能较好,那真的是这样么?

以下用AB两表,做个示例,两表都有一个id字段,而两个表都为id字段建立了索引

In

in的作用其实就是把范围内存在的数据做个返回,先看看下图的简单示例sql:

select * from A where id in (select id from B)

这句sql等价于两个循环:

for select id from B
for select * from A where A.id = B.id

其实就是对B表的id做个外层循环,而内层再嵌套一层A表的id循环,内层循环里判断A表和B表的id是否相等,相等的话就是要返回的数据。

Exists

exists的作用就是把主查询的数据,放到自查询中做条件的验证,结果是true则保留主查询中的结果,为false则不保留,以下用exists实现和in一样的效果:

select * from A where exists(select * from B where B.id = A.id)

这句sql也等价于两个循环:

for select * from A
for select * from B where B.id = A.id

其实就是对A表的id做个外层循环,而内层再嵌套一层B表的id循环,内层循环里判断B表和A表的id是否相等,相等的话就是要返回的数据。

这时引申出一个sql优化的规则:以小表驱动大表,mysql连接数会更少,sql性能会更佳

分析下,用in时,是in里面的表驱动外面的表,所以如果B表相对于A表是小表,用in比较好。而用exists时,是外面的表驱动exists里面的表,所以如果A表相对于B表是小表,则用exists比较好。

总结

明白了​​IN​​​和​​EXISTS​​​的原理后,配合上小表驱动大表的优化规则,可以得出用​​EXISTS​​​或者是用​​IN​​,还需要根据表中数据情况而定。

​IN​​​适合于外表大而内表小的情况,而​​EXISTS​​适合于外表小而内表大的情况。

况且大多数时候是没法用​​EXISTS​​​来替换​​IN​​的,比如如下语句

select * from user where id in(1,2,3)

这句语句有没有多表连接,就不适合用​​EXISTS​​​,而且坊间盛传的​​IN​​​不走索引,其实也是不对的