关联表查询是单表查询出结果后再用程序过滤还是直接用SQL语句查询最终结果
二者都有利弊吧,要从性能和易读易懂易维护各方面考虑,在什么场景下应该选哪种关联查询方式呢
二者都有利弊吧,要从性能和易读易懂易维护各方面考虑,在什么场景下应该选哪种关联查询方式呢
2018-11-01
首先,建表
create table users ( id int unsigned not null auto_increment, username char not null , enable tinyint not null default 0, primary key (id) )ENGINE=InnoDB default charset=utf8; alter table users add key key_username_enable(username, enable); create table orders ( id int unsigned not null auto_increment, username char not null , status char(10) not null default "unpay", amount char(30) not null , primary key (id) )ENGINE=InnoDB default charset=utf8;
可以看到 我这里给 users 加的索引是 (username,enable) 而不是 (enable)。
然后当我们用 explain 去分析你给的第一条 SQL 语句的时候,
select amount from orders where status="unpay" and username in (select username from users where enable = 0);
就会发现 users 表上面是使用了 `key_username_enable` 的,然后这个时候,根据索引的最左匹配原则,可以知道, mysql 把 username 这个条件下推了,所以这个时候,MySQL 对于上面的 SQL 语句的执行应该是类似于以下方式
select amount from orders where status="unpay" and exists (select orders.username from users where enable=0 and users.username=orders.username);
因此把它分成两部分来理解应该是
# 1. select amount,username from orders where status='unpay'; # 2. select username from users where enable=0 and username=?; #这里的?代表上一层传过来的参数
------------------------------------------------ 分割线 -------------------------------------------------------------------------------------------
好了, 其实上面的都是废话来的。
如果你是分开执行上面那两个 SQL 语句,对于 MySQL 来说,他所需要的时间是差不多的,
因为你如果是子查询,其实他也是先执行外部的找出一条数据,然后在进去子查询里面查询的,和在 Java 里面分开查询是一样的。
但是问题在于,如果是使用了子查询的话,那么你需要一次进程间通信,即 Java 给 MySQL 发送一次请求,然后 MySQL 查询完成之后返回数据。 但是如果是分开两次查询的话,那么网络通信的次数就变成了 1+(第一次结果集次),对于 MySQL 也好,Java 也好,他们的执行速度都是很快的,慢的是他们之间的通信,所以使用子查询的时候减少了他们之间通信的次数,同时需要发送的东西也少了,所以子查询会快一点。
举报