目录
1. 子查询概述
子查询通常是将一个表的查询结果作为另一个表的查询条件,也就是我们常说的嵌套查询。
使用子查询,我们让我们一次性完成需要很多步查询操作才能得到的结果。子查询的SQL语句通常比较长,而且执行效率普遍非常的差,是慢查询的主要贡献者,尽管它可以使用一条SQL语句达到查询效果,但实际并不是特别推荐使用,但我们在不得已的情况下也可以考虑使用子查询,那么我们就要最大程度上提高子查询的效率,这里就涉及到了子查询的优化。
2. 子查询效率低的原因
(1)执行子查询时,MySQL内部需要建立一个临时表来存储内部查询得到的数据,外层查询从内层查询的表中查询记录,查询完毕之后,会消除这个临时表,这个过程会非常消耗CPU资源和IO资源;
(2)因为子查询得到的结果是存储在一张临时表中,所以不论是内存临时表还是磁盘临时表,都无法添加索引,从查询效率自然非常差;
(3)如果子查询的结果集比较大,那么外查询的性能就会受到影响;
3. 子查询优化的方法
3.1 将子查询拆分为多表查询
嵌套查询通常情况都涉及到多张表,也有单表作为两张表的嵌套查询,分析哪张表数据量小,哪张表就作为驱动表,并在被驱动表的查询字段上添加索引,提高驱动表与被驱动表的匹配速度。
举一个最简单的子查询例子:
SELECT ... FROM ... WHERE ...NOT IN 或 NOT EXIST (内层查询 SELECT ... FROM... WHERE ...)
上述语句就是一个典型的嵌套子查询,这种情况下只有内层循环的 WHERE 可以使用到索引字段,外层的 NOT IN 条件过滤就无法使用索引过滤,只能挨个匹配判断;
我们可以将它改为多表连接查询SELECT .. FROM ... LEFT JOIN xxx ON xxx WHERE xx IS NULL。这样一来,我们在 JOIN 表连接时和 WHERE 条件判断时都可以使用到索引,从而提高查询效率。
3.2 在内部查询表的查询字段上添加索引
如果必须使用嵌套查询,暂且一双层嵌套为例,首先执行的是内部查询语句,它的执行过程与普通查询语句基本一致,但是查询所得到的结果则是一张虚拟表,无法向其中添加索引,只是为了给外部查询语句再次做条件筛选使用。因此,可以在内部查询表的查询字段上添加索引,如果有多个查询条件也可以考虑添加联合索引,通过提高内部查询的查询速度进而提升整体的查询性能。