本文主要记录一下在平时写 SQL 中的小表驱动大表,也就是子查询相关的优化,其实在 平时开发时,和写 for 循环遍历一样,都是用小的结果集去驱动大的结果集,以达到性能方面的提升,写 SQL 语句也是一样的,日常用的比较多的就是关键词 in 和 exists 了。
- 优化原则:小表驱动大表,即小的数据集驱动大的数据集
先来看一段 Java 代码:
//一、小结果集,驱动大结果集
for(int i = 0;i<10;i++) {
for(int j = 0;j<1000;j++) {
//TODO
...
}
}
//二、大结果集,驱动小结果集
for(int i = 0;i<1000;i++) {
for(int j = 0;j<10;j++) {
//TODO
...
}
}
以上 Java 代码中,我们通常采用第一种小结果集驱动大结果集的方式,那么在 SQL 中呢?
下面来看一下:
select * from A where id in (select id from B)
等价于:
for select id from B
for select * from A where A.id = B.id
当 B 表的数据集小于 A 表的数据集时,用 in 优于 exists.
select * from A where exists (select 1 from B where B.id = A.id)
等价于:
for select * from A
for select * from B where B.id = A.id
当 A 表的数据集小于 B 表的数据集时,用 exists 优于 in。
-
EXISTS
select … from table where exists (subquery)
该语法可以理解为: 将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE 或 FALSE)来决定主查询的数据结果是否得以保留。 -
提示
1、EXISTS (subquery) 只返回 TRUE 或 FALSE,因此子查询中的 select * 也可以是 select 1或者 select ‘X’,官方说法是实际执行时会忽略 select 清单,因此没有区别;
2、EXISTS 子查询的实际执行过程可能经过了优惠啊而不是我们理解上的逐条对比,如果担忧效率问题,可以进行实际检验以确定是否有效率问题;
3、EXISTS 子查询往往也可以用条件表达式,其他子查询或者 join 来替代,何种最优,需要具体问题具体分析。