MySQL - explain 输出信息详解

常用 SQL(假设表名是 student)

连接查询、联合查询、子查询:

查看表结构:
show create student;
desc student;

增删索引:
增加主键:alter table class add constraint primary key cid_pk(cid);
删除主键:alter table class drop primary key;
增加索引:alter table class add index cid_idx(cid); 或者 create index dexc_idx on class(cdesc);
删除索引:drop index sid on student;

查看表的索引:show index from student;

修改表的字符编码:alter table student charset = utf8mb4;
修改字段类型:alter table student modify name char(30) not null;

创建测试数据

create table class(
	cid int(10),
	cdesc varchar(20)
);

create table student(
	sid int(10),
	name varchar(20),
	age int(3),
	cid int(10)
);

create table teacher(
	tid int(10),
	name varchar(20),
	cid int(10)
);

insert into class values(1, "PHP"),(2, "Java"),(3, "C++"),(4,"SQL");
insert into student values(1, "s1",16,1),(2, "s2",17,2),(3, "s3",18,3),(4,"s4",19,4),(5, "s5",18,3),(6,"s6",19,4);
insert into teacher values(1, "t1",1),(2, "t2",2),(3, "t3",3),(4,"t4",4);

alter table student add constraint sid_pk primary key(sid);

MySQL 的解析过程

MySQL 中,每条 SQL 语句的解析都是按照指定的顺序来的,而不是从左到右,顺序为:
from -> on -> join -> where -> group by -> having -> select distinct -> order by -> limit
例如,对于下面一条 SQL:

select distinct sid from student s left join class c on s.cid = c.cid where s.age = 19 group by name having sid > 4 order by sid desc limit 5;

MySQL 解析过程为:

  • 先判断要查询的主表:student 表
  • 判断要用到的连接查询关联字段:cid
  • 连接查询的表:class 表
  • where 查询条件对应字段:s.age
  • group by 对应字段:name
  • having 对应字段:sid
  • 要查询的字段:sid
  • order by对应的字段:sid
  • limit 限制的查询条数:5

explain 的输出信息

官方文档:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

mysql> explain select * from s2;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | s2    | ALL  | NULL          | NULL | NULL    | NULL |   64 |       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

id:查询序号
select_type:查询类型
table:表名
type:索引命中类型
possible_keys:可利用的索引
key:实际利用的索引
key_len:索引长度
ref:引用
rows:扫描的数据行数
Extra:附加信息

id

如果 SQL 中有子查询,则每个子查询会对应一个 id,且最内层子查询的 id 最大,最大的 id 最先执行。
select t.* from class c,student s,teacher t where s.cid = c.cid and t.cid = c.cid and (s.id = 1 or s.name = ‘s2’);
如果 SQL 中没有子查询,则 id 这一列都相同,从上往下逐行执行。

select_type

select_type 查询类型

  • simple:简单查询,SQL 中没有子查询和 union
  • primary:主查询,SQL 中有子查询或 union 时最外层查询就是主查询
  • subquery:内层子查询,SQL 中有子查询时除了最外层查询都是
  • union:联合查询
  • union result:联合查询时的提示信息,说明是哪两张表
  • derived:衍生查询,查询过程中用到了临时表,分两种情况:
    • from 后面跟子查询,且只有一张表,例如:select s.name from (select * from student where sid < 5) s;,下图中 table 列的 derived2 就是衍生表,数字2表示的就是id列中的值
    • from 后面跟子查询,且使用 union 联合多个表时,左表是衍生查询,右表是联合查询,例如:select * from (select * from student where sid < 2 union select * from student where sid > 2) s;
  • dependent subquery:外部的主查询依赖子查询,例如:explain select * from student where sid in (select sid from student where sid > 3);
  • dependent union:子查询是联合查询,且外部的主查询依赖子查询,explain select * from student where sid in (select sid from student where sid < 2 union select sid from student where sid > 2);

select_type SQL 示例

simple

mysql> explain select * from student;
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | student | ALL  | NULL          | NULL | NULL    | NULL |    6 |       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

primary

union 和 union result 的情况

mysql> explain select * from student where sid < 2 union select * from student where sid > 2;
+----+--------------+------------+-------+---------------+------+---------+------+------+-------------+
| id | select_type  | table      | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+--------------+------------+-------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY      | student    | range | sid           | sid  | 5       | NULL |    1 | Using where |
|  2 | UNION        | student    | ALL   | sid           | NULL | NULL    | NULL |    6 | Using where |
| NULL | UNION RESULT | <union1,2> | ALL   | NULL          | NULL | NULL    | NULL | NULL |             |
+----+--------------+------------+-------+---------------+------+---------+------+------+-------------+
3 rows in set (0.00 sec)

子查询的情况

mysql> explain select * from student  where sid in (select sid from student where sid > 3);
+----+--------------------+---------+----------------+---------------+------+---------+------+------+--------------------------+
| id | select_type        | table   | type           | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+--------------------+---------+----------------+---------------+------+---------+------+------+--------------------------+
|  1 | PRIMARY            | student | ALL            | NULL          | NULL | NULL    | NULL |    6 | Using where              |
|  2 | DEPENDENT SUBQUERY | student | index_subquery | sid           | sid  | 5       | func |    1 | Using index; Using where |
+----+--------------------+---------+----------------+---------------+------+---------+------+------+--------------------------+
2 rows in set (0.02 sec)

subquery

mysql> explain select * from student where sid > (select sid from student where name = 's3');
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY     | student | ALL  | sid           | NULL | NULL    | NULL |    6 | Using where |
|  2 | SUBQUERY    | student | ALL  | NULL          | NULL | NULL    | NULL |    6 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+------+-------------+
2 rows in set (0.00 sec)

dependent subquery 和 dependent union 的情况

mysql> explain select * from student where sid in (select sid from student where sid < 2 union select sid from student wher
+----+--------------------+------------+------+---------------+------+---------+------+------+--------------------------+
| id | select_type        | table      | type | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+--------------------+------------+------+---------------+------+---------+------+------+--------------------------+
|  1 | PRIMARY            | student    | ALL  | NULL          | NULL | NULL    | NULL |    6 | Using where              |
|  2 | DEPENDENT SUBQUERY | student    | ref  | sid           | sid  | 5       | func |    1 | Using where; Using index |
|  3 | DEPENDENT UNION    | student    | ref  | sid           | sid  | 5       | func |    1 | Using where; Using index |
| NULL | UNION RESULT       | <union2,3> | ALL  | NULL          | NULL | NULL    | NULL | NULL |                          |
+----+--------------------+------------+------+---------------+------+---------+------+------+--------------------------+
4 rows in set (0.00 sec)

derived

from 后面跟子查询,且只有一张表

mysql> explain select s.name from (select * from student where sid < 5) s;
+----+-------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+------------+------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL | NULL    | NULL |    4 |             |
|  2 | DERIVED     | student    | ALL  | NULL          | NULL | NULL    | NULL |    6 | Using where |
+----+-------------+------------+------+---------------+------+---------+------+------+-------------+
2 rows in set (0.00 sec)

from 后面跟子查询,且使用 union 联合多个表时,左表是衍生查询,右表是联合查询

mysql> explain select * from (select * from student where sid < 2 union select * from student where sid > 2) s;
+----+--------------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type  | table      | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+--------------+------------+------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY      | <derived2> | ALL  | NULL          | NULL | NULL    | NULL |    5 |             |
|  2 | DERIVED      | student    | ALL  | NULL          | NULL | NULL    | NULL |    6 | Using where |
|  3 | UNION        | student    | ALL  | NULL          | NULL | NULL    | NULL |    6 | Using where |
| NULL | UNION RESULT | <union2,3> | ALL  | NULL          | NULL | NULL    | NULL | NULL |             |
+----+--------------+------------+------+---------------+------+---------+------+------+-------------+

type

没有索引或没有用到索引时,需要全量扫描所有数据。命中索引时,有各种不同的效果差异。

MySQL 中的索引,效果由好到差排序为:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,得保证查询至少达到 range 级别,最好能达到 ref。

类型说明

  • ALL:Full Table Scan,没用索引,全表扫描。
  • index:Full Index Scan,index 类型只遍历索引树。
  • range:在索引树中仅限范围扫描。key 列显示使用了哪个索引。对应操作符有 =、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符。其中 IN 可能退化为全表扫描 ALL。
  • ref:非唯一索引访问,返回所有匹配某个单个值的行。只有当使用非唯一索引或唯一索引的非唯一性前缀时才会发生。
  • eq_ref:唯一索引访问。最多只返回一条符合条件的记录。多表连接中使用 primary key 或者 unique key 作为关联条件。
  • const:表中最多只会有一行匹配,包括两种情况:where 条件中使用主键或 unique 唯一键。
  • system:要查询的表中(主表或衍生表)仅有一行数据。
  • Null:mysql能在优化阶段分解查询语句,在执行阶段甚至用不到访问表或索引。

type SQL 示例

system

要查询的表中(主表或衍生表)仅有一行数据。

mysql> select * from s1;
+-----+------+------+------+
| sid | name | age  | cid  |
+-----+------+------+------+
|   1 | s1   |   22 |    1 |
+-----+------+------+------+
1 row in set (0.00 sec)
mysql> explain select * from (select * from s1) s where sid = 1;
+----+-------------+------------+--------+---------------+------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+---------------+------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL | NULL    | NULL |    1 |       |
|  2 | DERIVED     | s1         | ALL    | NULL          | NULL | NULL    | NULL |    1 |       |
+----+-------------+------------+--------+---------------+------+---------+------+------+-------+
2 rows in set (0.00 sec)

const

用主键或唯一键做 where 条件。

mysql> show create table student\G
*************************** 1. row ***************************
       Table: student
Create Table: CREATE TABLE `student` (
  `sid` int(10) NOT NULL DEFAULT '0',
  `name` varchar(20) DEFAULT NULL,
  `age` int(3) DEFAULT NULL,
  `cid` int(10) DEFAULT NULL,
  PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> explain select * from student where sid = 3;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | student | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)

eq_ref

如果用主键做关联条件,效果更好:

mysql> alter table class add constraint primary key cid_pk(cid);
Query OK, 4 rows affected (0.23 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> explain select * from student s left join class c on s.cid = c.cid where s.sid = 3;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | s     | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
|  1 | SIMPLE      | c     | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
2 rows in set (0.00 sec)

ref

对于非唯一索引,用作 where 条件时,可能命中多行,此时 type 类型是 ref。

mysql> alter table student add index name_idx(name);
mysql> explain select * from student where name = 's3';
+----+-------------+---------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table   | type | possible_keys | key      | key_len | ref   | rows | Extra       |
+----+-------------+---------+------+---------------+----------+---------+-------+------+-------------+
|  1 | SIMPLE      | student | ref  | name_idx      | name_idx | 23      | const |    1 | Using where |
+----+-------------+---------+------+---------------+----------+---------+-------+------+-------------+
1 row in set (0.00 sec)

range

mysql> explain select * from student where name like 's3';
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows | Extra       |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
|  1 | SIMPLE      | student | range | name_idx      | name_idx | 23      | NULL |    1 | Using where |
+----+-------------+---------+-------+---------------+----------+---------+------+------+-------------+
1 row in set (0.00 sec)

index

全量扫描索引数据。

mysql> explain select sid from student;
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | student | index | NULL          | PRIMARY | 4       | NULL |    6 | Using index |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)

All

全量扫描表中的数据。

mysql> explain select * from student;
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | student | ALL  | NULL          | NULL | NULL    | NULL |    6 |       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

possible_keys

MySQL 优化器判断可能会用到的索引,实际未必使用。

key

实际利用的索引。NULL 时没有用到索引。

key_len

where 条件中,索引用到的字节数 。通常用来判断复合索引命中了几个字段。MySQL 中,对于字符串,utf8 每个字符占 3 个字节,utf8_mb4 每个字符占 4 个字节。

  • 对于允许 NULL 的字段,需要额外增加一个字节。例如 int 类型索引且不允许 null 时,key_len = 4,允许 null 时,key_len = 5。
  • 对于 varchar 变长字符串,需要额外增加二个字节。

首先创建测试表和测试数据:

create table filesort (
	f1 int(10),
	f2 int(10),
	f3 int(10),
	f4 int(10),
	index idx_f4(f4),
	index idx_f1_f2_f3(f1, f2, f3)
);
insert into filesort values(1, 2, 3, 4),(11, 12, 13, 14), (21, 22, 23, 24);

下面要查询的数据和 where 条件在同一个索引中,需要扫描全量索引数据。同时,索引字段都可以为 null,所以 key_len = (4 + 1) * 3 = 15:

mysql> explain select f2 from filesort where f3 = 3;
+----+-------------+----------+-------+---------------+--------------+---------+------+------+--------------------------+
| id | select_type | table    | type  | possible_keys | key          | key_len | ref  | rows | Extra                    |
+----+-------------+----------+-------+---------------+--------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | filesort | index | NULL          | idx_f1_f2_f3 | 15      | NULL |    3 | Using where; Using index |
+----+-------------+----------+-------+---------------+--------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

下面只用到了符合索引的第一个字段:

mysql> explain select f2 from filesort where f1 = 3;
+----+-------------+----------+------+---------------+--------------+---------+-------+------+--------------------------+
| id | select_type | table    | type | possible_keys | key          | key_len | ref   | rows | Extra                    |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | filesort | ref  | idx_f1_f2_f3  | idx_f1_f2_f3 | 5       | const |    1 | Using where; Using index |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

对于 char 和 varchar 类型,以及是否允许 null,示例如下:

mysql> alter table filesort modify f4 varchar(30);
Query OK, 3 rows affected (2.24 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> explain select f2,f4 from filesort where f4 = '';
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
| id | select_type | table    | type | possible_keys | key    | key_len | ref   | rows | Extra       |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
|  1 | SIMPLE      | filesort | ref  | idx_f4        | idx_f4 | 93      | const |    1 | Using where |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
1 row in set (0.00 sec)

mysql> alter table filesort modify f4 char(30) not null;
Query OK, 3 rows affected (2.03 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> explain select f2,f4 from filesort where f4 = '';
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
| id | select_type | table    | type | possible_keys | key    | key_len | ref   | rows | Extra       |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
|  1 | SIMPLE      | filesort | ref  | idx_f4        | idx_f4 | 90      | const |    1 | Using where |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
1 row in set (0.00 sec)

utf8mb4 编码格式:

mysql> alter table filesort charset = utf8mb4;
Query OK, 3 rows affected (2.08 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> alter table filesort modify f4 char(30) not null;
Query OK, 3 rows affected (0.25 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> explain select f2,f4 from filesort where f4 = '';
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
| id | select_type | table    | type | possible_keys | key    | key_len | ref   | rows | Extra       |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
|  1 | SIMPLE      | filesort | ref  | idx_f4        | idx_f4 | 120     | const |    1 | Using where |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
1 row in set (0.00 sec)

ref

哪些列或常量被用于查找索引列上的值。例如 where t1.id = t2.key 关联其他表的索引,where id = 3 用到了 const 常量。

mysql> explain select * from student where sid = 3;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | student | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
mysql> alter table class add index idx_cid(cid);
Query OK, 0 rows affected (1.97 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select * from student s,class c where s.cid = c.cid;
+----+-------------+-------+------+---------------+---------+---------+------------+------+-------------+
| id | select_type | table | type | possible_keys | key     | key_len | ref        | rows | Extra       |
+----+-------------+-------+------+---------------+---------+---------+------------+------+-------------+
|  1 | SIMPLE      | s     | ALL  | NULL          | NULL    | NULL    | NULL       |    6 |             |
|  1 | SIMPLE      | c     | ref  | idx_cid       | idx_cid | 5       | test.s.cid |    1 | Using where |
+----+-------------+-------+------+---------------+---------+---------+------------+------+-------------+
2 rows in set (0.00 sec)

rows

扫描的数据行数。估计值。

Extra:附加信息

  • Using filesort:需要一次额外的排序操作,尽量避免。常见于排序操作。
    • 单字段索引,如果排序和查找不是同一个字段,就会出现。
    • 组合索引如果不满足最左前缀原则,也会出现。
  • Using index:索引覆盖,要查询的数据都在索引中,性能高。
  • Using where:索引部分覆盖,还需要回表查询。
  • Using temporary:需要使用临时表来存储结果集,尽量避免,常见于分组查询。
  • Using join buffer:改值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。
  • Impossible WHERE:where 语句导致没有符合条件的行,例如 where f1 = 3 and f1 = 4
  • Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行

Using filesort

使用无索引的字段、不在 where 条件中的有索引字段、有组合索引但是没有命中,这三种情况下进行 order by 排序时,会多一次排序操作。首先创建测试表和测试数据:

create table filesort (
	f1 int(10),
	f2 int(10),
	f3 int(10),
	f4 int(10),
	index idx_f4(f4),
	index idx_f1_f2_f3(f1, f2, f3)
);
insert into filesort values(1, 2, 3, 4),(11, 12, 13, 14), (21, 22, 23, 24);

对于单列索引,如果 order by 的字段已经出现在 where 条件中,则不会出现 filesort:

mysql> explain select * from filesort where f4 = 1 order by f4;
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
| id | select_type | table    | type | possible_keys | key    | key_len | ref   | rows | Extra       |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
|  1 | SIMPLE      | filesort | ref  | idx_f4        | idx_f4 | 5       | const |    1 | Using where |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from filesort where f4 = 1 order by f3;
+----+-------------+----------+------+---------------+--------+---------+-------+------+-----------------------------+
| id | select_type | table    | type | possible_keys | key    | key_len | ref   | rows | Extra                       |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | filesort | ref  | idx_f4        | idx_f4 | 5       | const |    1 | Using where; Using filesort |
+----+-------------+----------+------+---------------+--------+---------+-------+------+-----------------------------+
1 row in set (0.00 sec)

对于组合索引,则必须匹配组合索引的前缀,否则还是会出现 filesort:

mysql> explain select * from filesort where f1 = 1 and f2 = 2 order by f3;
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-------------+
| id | select_type | table    | type | possible_keys | key          | key_len | ref         | rows | Extra       |
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-------------+
|  1 | SIMPLE      | filesort | ref  | idx_f1_f2_f3  | idx_f1_f2_f3 | 10      | const,const |    1 | Using where |
+----+-------------+----------+------+---------------+--------------+---------+-------------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from filesort where f1 = 1 order by f3;
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-----------------------------+
| id | select_type | table    | type | possible_keys | key          | key_len | ref   | rows | Extra                       |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | filesort | ref  | idx_f1_f2_f3  | idx_f1_f2_f3 | 5       | const |    1 | Using where; Using filesort |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+-----------------------------+
1 row in set (0.00 sec)

Using index

要查询的数据跟 where 条件命中索引,效率高:

mysql> explain select f2 from filesort where f3 = 3;
+----+-------------+----------+-------+---------------+--------------+---------+------+------+--------------------------+
| id | select_type | table    | type  | possible_keys | key          | key_len | ref  | rows | Extra                    |
+----+-------------+----------+-------+---------------+--------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | filesort | index | NULL          | idx_f1_f2_f3 | 15      | NULL |    3 | Using where; Using index |
+----+-------------+----------+-------+---------------+--------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

mysql> explain select f2 from filesort where f1 = 3;
+----+-------------+----------+------+---------------+--------------+---------+-------+------+--------------------------+
| id | select_type | table    | type | possible_keys | key          | key_len | ref   | rows | Extra                    |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | filesort | ref  | idx_f1_f2_f3  | idx_f1_f2_f3 | 5       | const |    1 | Using where; Using index |
+----+-------------+----------+------+---------------+--------------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

你可能感兴趣的:(数据库)