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用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值TrueFalse

    当子查询返回为真时,则外层查询语句将进行查询。
    当子查询返回为假时,外层查询语句将不进行查询或者查询不出任何记录。

    所以,下面这样的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的区别的主要内容,如果未能解决你的问题,请参考以下文章

MySQL-IN和Exists区别

MySQL EXISTS和in的区别

MySQL中exists和in的区别及使用场景

mysql查询语句in和exists二者的区别和性能影响

(转)MySQL中In与Exists的区别

查询优化--小表驱动大表(In,Exists区别)