mysql中=与in区别_浅析mysql中exists与in的区别,空判断
1、exists的使⽤
exists对外表⽤loop逐条查询,每次查询都会查看exists的条件语句,当exists⾥的条件语句能够返回记录⾏时(⽆论记录⾏是的多少,只要能返回),条件就为真,返回当前loop到的这条记录;
反之如果exists⾥的条件语句不能返回记录⾏,则当前loop到的这条记录被丢弃,exists的条件就像⼀个bool条件,当能返回结果集则为true,不能返回结果集则为 false。
如下:
select * from user where exists (select 1);
对user表的记录逐条取出,由于⼦条件中的select 1永远能返回记录⾏,那么user表的所有记录都将被加⼊结果集,所以与 select * from user;是⼀样的。
如下:
select * from user where exists (select * from user where userId = 0);
可以知道对user表进⾏loop时,检查条件语句(select * from user where userId = 0),由于userId永远不为0,所以条件语句永远返回空集,条件永远为false,那么user表的所有记录都将被丢弃。
not exists与exists相反,也就是当exists条件有结果集返回时,loop到的记录将被丢弃,否则将loop到的记录加⼊结果集。
总的来说,如果A表有n条记录,那么exists查询就是将这n条记录逐条取出,然后判断n遍exists条件。
2、in 的使⽤
in查询相当于多个or条件的叠加,这个⽐较好理解,⽐如下⾯的查询:
select * from user where userId in (1, 2, 3);
等效于
select * from user where userId = 1 or userId = 2 or userId = 3;
not in 与 in相反,如下
select * from user where userId not in (1, 2, 3);
等效于
select * from user where userId != 1 and userId != 2 and userId != 3;
总的来说,in查询就是先将⼦查询条件的记录全都查出来,假设结果集为B,共有m条记录,然后再将⼦查询条件的结果集分解成m个,再进⾏m次查询。
值得⼀提的是,in查询的⼦条件返回结果必须只有⼀个字段,例如:
select * from user where userId in (select id from B);
⽽不能是
select * from user where userId in (select id, age from B);
3.1、exists 与 in 的⽐较
下⾯来考虑exists和in的性能,考虑如下SQL语句。
前提条件:表A(⼩表),表B(⼤表)。
查询1:
select * from A where exists (select * from B where B.id = A.id);
查询2:
select * from A where A.id in (select id from B);
以上查询使⽤了in语句,in()只执⾏⼀次,它查出B表中的所有id字段并缓存起来。之后检查A表的id是否与B表中的id相等,如果相等则将A 表的记录加⼊结果集中,直到遍历完A表的所有记录。
可以看出,当B表数据较⼤时不适合使⽤in(),因为它会B表数据全部遍历⼀次。
如:A表有10000条记录,B表有1000000条记录,那么最多有可能遍历10000*1000000次,效率很差。
再如:A表有10000条记录,B表有100条记录,那么最多有可能遍历10000*100次,遍历次数⼤⼤减少,效率⼤⼤提升。
以上查询使⽤了exists语句,exists()会执⾏A.length次,它并不缓存exists()结果集,因为exists()结果集的内容并不重要;重要的是结果集中是否有记录,如果有则返回true,没有则返回false。
当B表⽐A表数据⼤时适合使⽤exists(),因为它没有那么多的遍历操作,只需要再执⾏⼀次查询就⾏。
如:A表有10000条记录,B表有1000000条记录,那么exists()会执⾏10000次去判断A表中的id是否与B表中的id相等。
如:A表有10000条记录,B表有100000000条记录,那么exists()还是执⾏10000次,因为它只执⾏A.length次,可见B表数据越多,越适合exists()发挥效果。
再如:A表有10000条记录,B表有100条记录,那么exists()还是执⾏10000次,还不如使⽤in()遍历10000*100次,因为in()是在内存⾥遍历⽐较,⽽exists()需要查询数据库,我们都知道查询数据库所消耗的性能更⾼,⽽内存⽐较很快。
3.2、not exists 与 not in⽐较
查询1:
select * from A where not exists (select * from B where B.id = A.id);
查询2:
select * from A where A.id not in (select id from B);
not in是个范围查询,这种!=的范围查询⽆法使⽤任何索引,那么内外表都进⾏全表扫描,没有⽤到索引;
⽽not extsts 的⼦查询依然能⽤到表上的索引;
所以⽆论那个表⼤,⽤not exists都⽐not in要快
3.3、in 与 = 的区别
select name from student where name in ('zhang','wang','li','zhao');
select name from student where name='zhang' or name='li' or name='wang' or name='zhao' ;
的结果是相同的。exists子查询
4.空判断 is null、is not null
总结:
如果查询的两个表⼤⼩相当,那么⽤in和exists差别不⼤。
如果两个表中⼀个较⼩,⼀个是⼤表,则⼦查询表⼤的⽤exists,⼦查询表⼩的⽤in。
mysql中的in语句是把外表和内表作hash 连接,⽽exists语句是对外表作loop循环,每次loop循环再对内表进⾏查询。⼀直⼤家都认为exists ⽐in语句的效率要⾼,这种说法其实是不准确的。这个是要区分环境的。