| 类型 | 释义 |
| — | — |
| Using index | 查询语句只扫描一次索引树即获得了目标数据,效率很高,一般是通过索引列查询主键或查询与索引列建有联合索引的列 |
| Using where Using index | 无法直接通过索引查找来查询到符合条件的数据,一般是使用索引前导列进行范围查询或通过索引的非前导列查询 |
| Using index condition | 查询列的某一部分无法直接使用索引,一般是WHERE
条件列是索引前导列且是范围查询导致的 |
| NULL | WHERE条件是索引前导列,但查询列至少有一个未与条件列在同一个索引树上,必须通过回表查询 |
| Using where | WHERE
条件列上无索引(既没有单独索引,也没有联合索引),而与查询列无关 |
| Using filesort | MySQL需要创建一张内部临时表来处理查询,通常在许多执行包括DISTINCT、GROUP BY、ORDER BY
等子句查询过程中,如果不能有效利用索引来完成查询,MySQL很有可能会寻求建立内部临时表来执行查询 |
| Using filesort | 当SQL中使用ORDER BY
关键字的时候,如果待排序的内容不能由所使用的索引直接完成排序的话,那么mysql有可能就要进行文件排序 |
| Index merges | 对多个索引分别进行条件扫描,然后将它们各自的结果进行合并(intersect/union),一般出现AND和OR查询 |
下面,我会构造测试表与数据,详细演示每一个案例,请做好战斗准备!感兴趣的同学,可以自己建表动手测试一下,毕竟纸上得来终觉浅,绝知此事要躬行。演示数据在文末。
id
列是 SELECT
的序列号,其顺序是按 SELECT
出现顺序增长的。id
列越大执行优先级越高,id
相同则从上往下执行,id
为 NULL
最后执行。
MySQL将 SELECT
查询分为简单查询 SIMPLE
和复杂查询 PRIMARY
。复杂查询包括:简单子查询、派生表( FROM 语句中的子查询)、UNION 和 UNION ALL 查询。
1、SUBQUERY
在SELECT
或WHERE
中包含了子查询,例如:
EXPLAIN SELECT (SELECT 1 FROM student LIMIT 1) FROM student;
WHERE
条件中含子查询,select_type也会出现PRIMARY
与SUBQUERY
:
EXPLAIN SELECT id FROM student WHERE id = (SELECT s_id id FROM class_student WHERE c_id=3)
2、DERIVED
FROM
中包含的子查询被标记为DERIVED
,最外层查询被标记为PRIMARY
,如下面这个SQL:
EXPLAIN SELECT * FROM (SELECT * FROM student GROUP BY id) AS temp;
3、UNION和UNION ALL
UNION
和UNION ALL
是对两个SQL结果进行纵向合并,即列数不变,行数增
加,前者对合并结果去重,后者不去重。
因此,UNION 会将合并结果放在一个匿名临时表中进而做去重操作,临时表不在 SQL 中出现,临时表名为 <union1, 2>,因此它的 id 是 NULL,表明这个临时表是为了合并两个查询结果集而创建的。
EXPLAIN SELECT * FROM student WHERE id =1 UNION SELECT * FROM student
UNION ALL 无需为合并结果去重,仅是将多个查询结果集中的记录合并成一个,所以不会使用到临时表,故没有 id 为 NULL 记录:
EXPLAIN SELECT * FROM student WHERE id =1 UNION ALL SELECT * FROM student