MySQL EXISTS和in的区别
Posted Java程序员驿站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL EXISTS和in的区别相关的知识,希望对你有一定的参考价值。
mysql中exists和in是常用的两个关键字,他们之间有什么区别呢?今天我们就来研究一下,首先创建两张表,用户表tbUsers和订单表tbOrders。
CREATE TABLE `tbUsers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `tbOrders` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userId` int(11) NOT NULL,
`paytime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
表结构如上所示,我们来查询用户表中有过订单的用户信息。
exists
SELECT * FROM tbUsers WHERE EXISTS ( SELECT * FROM tbOrders WHERE tbOrders.userId = tbUsers.id )
in
SELECT * FROM tbUsers WHERE id IN (SELECT userId FROM tbOrders);
我们可以用上面两种方式实现查询数据的需求,他们之间有什么区别呢?回答这个问题之前我们先来看看exists是什么?
exists用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False。
当子查询返回为真时,则外层查询语句将进行查询。
当子查询返回为假时,外层查询语句将不进行查询或者查询不出任何记录。
所以,下面这样的sql也是可以正常执行的。
SELECT * FROM tbUsers WHERE EXISTS (SELECT NULL);
区别
exists适合于外查询数据少子查询数据多的场景,in则适合外查询数据多子查询数据少的情况。
in语句只会执行一次,它查出tbOrders表中的所有userId字段并且缓存起来,之后,检查tbUsers表的id是否和tbOrders表中的userId相当,如果相等则加入结果集,直到遍历完user的所有记录,执行过程类似如下代码
List<User> result = new ArrayList<User>();//存放结果
List<User> users= new ArrayList<User>();//模拟users表数据
List<Order> orders = new ArrayList<Order>();//模拟order表数据
for(User u:users) {
for(Order o:orders) {
if(o.getUserId()==u.getId()) {
result.add(u);
}
}
}
如上所示,in会将orders表中所有数据遍历一遍,所以不太适合orders表中是数据太多的场景。
exists不会缓存子查询的结果集,因为子查询的结果并不重要,只需要返回true或者false即可。执行过程类似如下代码
List<User> result = new ArrayList<User>();// 存放结果
List<User> users = new ArrayList<User>();// 模拟users表数据
for (User u : users) {
// 相当于执行SELECT * FROM tbOrders WHERE tbOrders.userId = tbUsers.id
if (exists(u.getId)) {
result.add(u);
}
}
所以,当tbOrders中数据量大的时候,适合用exists查询,因为不会遍历,只是会查询一次结果即可。
总结:
exists是对外表做loop循环,每次loop循环再对内表(子查询)进行查询,那么因为对内表的查询使用的索引(内表效率高,故可用大表),而外表有多大都需要遍历,不可避免(尽量用小表),故内表大的使用exists,可加快效率;
in是把外表和内表做hash连接,先查询内表,再把内表结果与外表匹配,对外表使用索引(外表效率高,可用大表),而内表多大都需要查询,不可避免,故外表大的使用in,可加快效率。
如果查询的两个表大小相当,那么用in和exists差别不大。如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in。
以上是关于MySQL EXISTS和in的区别的主要内容,如果未能解决你的问题,请参考以下文章