MySQL-执行计划(三)
1. 前言
本文主要分为三个部分,第一个部分讲解
MySQL
查询时会经过哪些过程;第二个部分讲解Explain
的基本用法;第三个部分讲解Explain
参数分析。如下很多操作只是一些基本的操作,如果相对
MySQL
进行深层次的学习还是要对 B+ 树有一定了解准备工作
- 导入
SQL
文件:explain_demo_test.sql 之后会有三张表(actor、film、film_actor)
2. MySQL
查询过程
服务器程序处理来自客户端的查询请求大致需要经过三个部分 : 连接管理、解析与优化、存储引擎。
MySQL
查询过程如下:
- 客户端将查询发送到
MySQL
服务器 - 服务器先检查查询缓存,如果命中,立即返回缓存中的结果;否则进入下一阶段
- 服务器对
SQL
进行解析、预处理,再由优化器生成对象的执行计划 MySQL
根据优化器生成的执行计划,调用存储引擎API
来执行查询- 服务器将结果返回给客户端,同时缓存查询结果
3. Explain 基本介绍
3.1. Explain 是什么?
MySQL
的 Explain 是一个用于查看 SELECT、INSERT、UPDATE、DELETE 语句 执行计划 的命令。- 执行计划:指
SQL
语句在经过MySQL
查询优化器 的优化会后,具体的执行方式。
3.2. Explain 解决了那些问题?
- 它可以帮助我们了解查询执行计划,并识别潜在的性能问题。
3.3. Explain 如何使用?
- 语法
1 | # 第一条:SQL基础执行信息 |
- 示例
1 | mysql> explain extended SELECT * FROM actor;show warnings; |
4. Explain 参数分析
- 每张表对应的索引情况,使用Explain得到的结果都不一样,执行 Explain 请对照索引情况看
select 的序列号,表示优化器访问表的顺序。
- 序号越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行
查询数据的操作类型(简单、复杂),表示使用的 SELECT 语句的类型
- simple:简单查询,单表查询
- primary:复杂查询中最外层的 select
- subquery:包含在 select 中的子查询(不在 from 子句中)
- derived:包含在 from 子句中的子查询,也称为派生表(derived)
查询数据的操作类型(简单、复杂),表示使用的 SELECT 语句的类型
- 表示被访问的表的名称
匹配的分区信息,不用管
表示访问表的关联类型或者连接类型。一些常见的连接类型包括:
- system:正在访问只有一行的表。
- const:使用具有唯一或主键约束的索引列访问表。
- eq_ref:使用唯一索引或主键访问表。
- ref:使用非唯一索引访问表。
- range : 使用一个索引来检索给定范围的行, 通常出现在 in(), between ,> ,<, >= 等操作中
- index:只遍历索引树。
- ALL:全表扫描,性能最拉垮。
优先级排序:system > const > eq_ref > ref > range > index > ALL
通常优化至少到 range 级别,最好能优化到ref
查询数据可能使用哪些索引来查找
- 如果该列是NULL,则没有使用索引
显示 MySQL 实际使用的索引
- 如果为 NULL,则没有使用索引查询
表示索引中使用的字节数,通过该列计算查询中使用的索引的长度
表的索引字段关联了哪张表的哪个字段或常量
- const(常量)
- 字段名(例:film.id)
估算出找到所需的记录或所需读取的行数
- 数值越小越好
结果的行数占读取行数的百分比
- 值越大越好
十分重要的额外信息,如下是常见的值
- Using index:使用覆盖索引。
- Using where:使用 where 语句来处理结果,并且查询的列未被索引覆盖。
- Using index condition:查询的列不完全被索引覆盖,where条件中是一个前导列的范围;
- Using temporary:mysql需要创建一张临时表来处理查询。
- Using filesort:外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。
- Select tables optimized away:使用某些聚合函数(比如 max、min)来访问存在索引的某个字段
4.1. id
id:select 查询序列号
- 序号越大执行优先级越高;
- id相同,执行顺序由上至下;
- id不同,id值越大优先级越高,越先被执行;
- id为NULL最后执行;
4.2. select_type
select_type:select_type 表示对应行是简单还是复杂的查询
- SIMPLE : 简单查询,一般指单表查询。
- DERIVED :派生表,包含在 from 子句中的子查询。
- PRIMARY :复杂查询,一般指最外层的 select。
- SUBQUERY :包含在 select 中的子查询(不在 from 子句中) 。
- UNION : 表示使用 UNION 运算符的 SELECT 语句。
- 示例
1 | #关闭mysql5.7新特性对衍生表的合并优化 |
4.3. table
table:这一列表示 explain 的一行正在访问哪个表。
- 当 from 子句中有子查询时,table 列是
格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。
衍生表
- 执行这行如果想要得到衍生表,需要执行以下两条语句:
1 | #关闭mysql5.7新特性对衍生表的合并优化 |
4.4. type
type:这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围。
依次从最优到最差分别为,一般来说,得保证查询达到range级别,最好达到ref:
- null
- system
- const
- eq_ref
- ref
- range
- index
- ALL
NULL
mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。
1
2
3
4
5
6
7mysql> explain select min(id) from film;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
1 row in set (0.05 sec)const, system
mysql能对查询的某部分进行优化并将其转化成一个常量,所以表最多有一个匹配行,读取1次,速度比较快。
system是const的特例,表里只有一条元组匹配时为system
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16mysql> explain extended select * from (select * from film where id = 1) tmp;show warnings;
+----+-------------+------------+------------+--------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+--------+---------------+---------+---------+-------+------+----------+-------+
| 1 | PRIMARY | <derived2> | NULL | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 2 | DERIVED | film | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |
+----+-------------+------------+------------+--------+---------------+---------+---------+-------+------+----------+-------+
2 rows in set (0.10 sec)
+---------+------+-------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+-------------------------------------------------------------------+
| Warning | 1681 | 'EXTENDED' is deprecated and will be removed in a future release. |
| Note | 1003 | /* select#1 */ select '1' AS `id`,'film1' AS `name` from dual |
+---------+------+-------------------------------------------------------------------+
2 rows in set (0.05 sec)eq_ref
primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。
这可能是在const 之外最好的联接类型了,简单的 select 查询不会出现这种 type。
1
2
3
4
5
6
7
8
9# 其中 film表 使用的是主键索引, film_actor使用的是联合索引 NDEX `idx_film_actor_id`(`film_id`, `actor_id`) USING BTREE
mysql> explain select * from film_actor left join film on film_actor.film_id = film.id;
+----+-------------+------------+------------+--------+---------------+---------+---------+--------------------------------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+--------+---------------+---------+---------+--------------------------------------+------+----------+-------+
| 1 | SIMPLE | film_actor | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL |
| 1 | SIMPLE | film | NULL | eq_ref | PRIMARY | PRIMARY | 4 | explain_demo_test.film_actor.film_id | 1 | 100.00 | NULL |
+----+-------------+------------+------------+--------+---------------+---------+---------+--------------------------------------+------+----------+-------+
2 rows in set (0.02 sec)ref
相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。
1. 普通索引
file
表的信息1
2
3
4
5
6
7file表的索引信息
- 主键索引:PRIMARY KEY (`id`)
- 联合索引:INDEX `idx_name`(`name`)
file表的字段类型
- `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID'
- `name` varchar(10) DEFAULT NULL COMMENT '电影名称'Explain 分析结果
1
2
3
4
5
6
7mysql> explain select * from film where name = 'film1';
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | film | NULL | ref | idx_name | idx_name | 33 | const | 1 | 100.00 | Using index |
+----+-------------+-------+------------+------+---------------+----------+---------+-------+------+----------+-------------+
1 row in set (0.68 sec)
2. 唯一性索引的部分前缀
表的信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17file 表的索引信息
- 主键索引:PRIMARY KEY (`id`)
- 联合索引:KEY `idx_name`(`name`)
file 表的字段类型
- `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID'
- `name` varchar(10) DEFAULT NULL COMMENT '电影名称'
film_actor 表的索引信息
- 主键索引:PRIMARY KEY (`id`)
- 联合索引:KEY `idx_film_actor_id` (`film_id`,`actor_id`)
film_actor 表的字段类型
- `id` int(11) NOT NULL COMMENT '主键ID'
- `film_id` int(11) NOT NULL COMMENT '电影ID'
- `actor_id` int(11) NOT NULL COMMENT '演员ID'
- `remark` varchar(255) DEFAULT NULL COMMENT '备注'Explain 分析结果
1
2
3
4
5
6
7
8mysql> explain select film_id from film left join film_actor on film.id = film_actor.film_id;
+----+-------------+------------+------------+-------+-------------------+-------------------+---------+---------------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+-------------------+-------------------+---------+---------------------------+------+----------+-------------+
| 1 | SIMPLE | film | NULL | index | NULL | idx_name | 33 | NULL | 3 | 100.00 | Using index |
| 1 | SIMPLE | film_actor | NULL | ref | idx_film_actor_id | idx_film_actor_id | 4 | explain_demo_test.film.id | 1 | 100.00 | Using index |
+----+-------------+------------+------------+-------+-------------------+-------------------+---------+---------------------------+------+----------+-------------+
2 rows in set (0.03 sec)
range
范围扫描通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。
1
2
3
4
5
6
7mysql> explain select * from actor where id > 1;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | actor | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 2 | 100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set (0.04 sec)index
扫描全索引就能拿到结果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接对二级索引的叶子节点遍历和扫描,速度还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这种通常比ALL快一些。
1
2
3
4
5
6
7
8mysql> explain select * from film;
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
| 1 | SIMPLE | film | NULL | index | NULL | idx_name | 33 | NULL | 3 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
1 row in set (0.03 sec)ALL
即全表扫描,扫描你的聚簇索引的所有叶子节点。通常情况下这需要增加索引来进行优化了。
1
2
3
4
5
6
7
8mysql> explain select * from actor;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | actor | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set (0.04 sec)
4.5. possible_keys
possible_keys列表示在某个查询语句中,对某个表执行单表查询时可能用到的索引有哪些
如果该列是NULL,则没有相关的索引。
注意
possible_keys列中的值并不是越多越好,可能使用的索引越多,查询优化器计算查询成本时就得花费更长时间,所以如果可以的话,尽量删除那些用不到的索引
4.6. key
key列表示实际用到的索引有哪些,如果没有使用索引,则该列是 NULL
4.7. key_len
key_len列表示当优化器决定使用某个索引执行查询时,该索引记录的最大长度.
- 表的信息
1 | film_actor 表的索引信息 |
key_len 为什么为4?
因为走到了索引 idx_film_actor_id ,而 字段(film_id)数据类型是int , int就是占四个字节
1 | mysql> explain select * from film_actor where film_id = 2; |
key_len 计算规则如下
字符串
- 5.0.3以后版本中,n均代表字符数,而不是字节数,如果是utf-8,一个数字或字母占1个字节,一个汉字占3个字节
- char(n):如果存汉字长度就是 3n 字节
- varchar(n):如果存汉字则长度是 3n + 2 字节,加的2字节用来存储字符串长度,因为varchar是变长字符串
- 例如:某个索引列的类型是VARCHAR(100),使用的字符集是utf8,那么该列实际占用的最大存储空间就是100 × 3 = 300个字节
数值类型
- tinyint:1字节
- smallint:2字节
- int:4字节
- bigint:8字节
时间类型
- date:3字节
- timestamp:4字节
- datetime:8字节
NULL
- 如果字段允许为 NULL,需要1字节记录是否为 NULL
4.8. ref
这一列显示了在key列记录的索引中,表查找值所用到的列或常量
常见的有:const(常量),字段名(例:film.id)
4.9. rows
这一列是mysql估计要读取并检测的行数,注意这个不是结果集里的行数。
4.10. filtered
对于单表而言这个列没啥意义,结果函数占总数的百分比。
4.11. Extra
这一列展示的是额外信息。常见的重要值如下:
- Using index(覆盖索引)
- Using where(查询的列未被索引覆盖)
- Using index condition(不完全被索引覆盖)
- Using temporary
- Using filesort
- Select tables optimized away
Using index(覆盖索引)
mysql执行计划explain结果里的key有使用索引,如果 select 后面查询的字段都可以从这个索引的树中获取,这种情况可以说是用到了覆盖索引,extra里一般都有using index;
表信息
1
2
3
4
5
6
7
8
9film_actor 表的索引信息
- 主键索引:PRIMARY KEY (`id`)
- 联合索引:KEY `idx_film_actor_id` (`film_id`,`actor_id`)
film_actor 表的字段类型
- `id` int(11) NOT NULL COMMENT '主键ID'
- `film_id` int(11) NOT NULL COMMENT '电影ID'
- `actor_id` int(11) NOT NULL COMMENT '演员ID'
- `remark` varchar(255) DEFAULT NULL COMMENT '备注'示例
1
2
3
4
5
6
7mysql> explain select film_id from film_actor where film_id = 1;
+----+-------------+------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | film_actor | NULL | ref | idx_film_actor_id | idx_film_actor_id | 4 | const | 2 | 100.00 | Using index |
+----+-------------+------------+------------+------+-------------------+-------------------+---------+-------+------+----------+-------------+
1 row in set (19.56 sec)
Using where(查询的列未被索引覆盖)
使用 where 语句来处理结果,并且查询的列未被索引覆盖
表信息
1
2
3
4
5
6
7
8
9
10
11
12
13actor 表的索引信息
- 主键索引:PRIMARY KEY (`id`)
actor 表的字段类型
- `id` int(11) NOT NULL COMMENT '主键ID'
- `name` varchar(45) DEFAULT NULL COMMENT '演员名称'
- `update_time` datetime DEFAULT NULL COMMENT '更新时间'
- 主键索引:PRIMARY KEY (`id`)
actor 表的字段类型
- `id` int(11) NOT NULL COMMENT '主键ID'
- `name` varchar(45) DEFAULT NULL COMMENT '演员名称'
- `update_time` datetime DEFAULT NULL COMMENT '更新时间'示例
1
2
3
4
5
6
7mysql> explain select * from actor where name = 'a';
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | actor | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set (0.03 sec)
Using index condition(不完全被索引覆盖)
查询的列不完全被索引覆盖,where条件中是一个前导列的范围;
表信息
1
2
3
4
5
6
7
8
9film_actor 表的索引信息
- 主键索引:PRIMARY KEY (`id`)
- 联合索引:KEY `idx_film_actor_id` (`film_id`,`actor_id`)
film_actor 表的字段类型
- `id` int(11) NOT NULL COMMENT '主键ID'
- `film_id` int(11) NOT NULL COMMENT '电影ID'
- `actor_id` int(11) NOT NULL COMMENT '演员ID'
- `remark` varchar(255) DEFAULT NULL COMMENT '备注'示例
1
2
3
4
5
6
7mysql> explain select * from film_actor where film_id > 1;
+----+-------------+------------+------------+-------+-------------------+-------------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+-------+-------------------+-------------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | film_actor | NULL | range | idx_film_actor_id | idx_film_actor_id | 4 | NULL | 1 | 100.00 | Using index condition |
+----+-------------+------------+------------+-------+-------------------+-------------------+---------+------+------+----------+-----------------------+
1 row in set (0.03 sec)
Using temporary
mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先是想到用索引来优化。
表信息
1
2
3
4
5
6
7
8
9actor 表的索引信息
- 主键索引:PRIMARY KEY (`id`)
actor 表的字段类型
- `id` int(11) NOT NULL COMMENT '主键ID'
- `name` varchar(45) DEFAULT NULL COMMENT '演员名称'
- `update_time` datetime DEFAULT NULL COMMENT '更新时间'
actor.name 没有索引,此时创建了张临时表来distinct示例
1
2
3
4
5
6
7
8mysql> explain select distinct name from actor;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| 1 | SIMPLE | actor | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using temporary |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------+
1 row in set (0.03 sec)film.name 建立了idx_name索引,此时查询时extra是using index,没有用临时表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 新增 idx_name 索引
mysql> ALTER TABLE `film` ADD INDEX `idx_name`(`name`) USING BTREE;
Query OK, 0 rows affected (0.09 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain select distinct name from film;
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
| 1 | SIMPLE | film | NULL | index | idx_name | idx_name | 33 | NULL | 3 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
1 row in set (0.04 sec)
# 删除 idx_name 索引
mysql> ALTER TABLE `film` DROP INDEX `idx_name`;
Query OK, 0 rows affected (1.78 sec)
Records: 0 Duplicates: 0 Warnings: 0
Using filesort
将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。
表信息
1
2
3
4
5
6
7actor 表的索引信息
- 主键索引:PRIMARY KEY (`id`)
actor 表的字段类型
- `id` int(11) NOT NULL COMMENT '主键ID'
- `name` varchar(45) DEFAULT NULL COMMENT '演员名称'
- `update_time` datetime DEFAULT NULL COMMENT '更新时间'actor.name未创建索引,会浏览actor整个表,保存排序关键字name和对应的id,然后排序name并检索行记录
1
2
3
4
5
6
7mysql> explain select * from actor order by name;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
| 1 | SIMPLE | actor | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 100.00 | Using filesort |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
1 row in set (20.78 sec)film.name建立了idx_name索引,此时查询时extra是using index
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# 新增 idx_name 索引
mysql> ALTER TABLE `film` ADD INDEX `idx_name`(`name`) USING BTREE;
Query OK, 0 rows affected (0.09 sec)
Records: 0 Duplicates: 0 Warnings: 0
# Extra:Using index。添加idx_name 索引之后使用到了覆盖索引
mysql> explain select * from film order by name;
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
| 1 | SIMPLE | film | NULL | index | NULL | idx_name | 33 | NULL | 3 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+-------------+
1 row in set (0.20 sec)
# 删除 idx_name 索引
mysql> ALTER TABLE `film` DROP INDEX `idx_name`;
Query OK, 0 rows affected (1.78 sec)
Records: 0 Duplicates: 0 Warnings: 0
Select tables optimized away
使用某些聚合函数(比如 max、min)来访问存在索引的某个字段
- 示例
1
2
3
4
5
6
7mysql> explain select min(id) from film;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
1 row in set (0.11 sec)