一文读懂MySQL执行计划 Explain"/>
一文读懂MySQL执行计划 Explain
MySQL执行计划 Explain
文章相关示例执行 基于MySQL(8.0.13)版本
定义
官方文档描述的定义如下:
The set of operations that the optimizer chooses to perform the most efficient query is called the “query execution plan”, also known as the EXPLAIN plan.
MySQL优化器选择执行最有效的查询的一组操作称为“查询执行计划”,也称为解释计划。
执行计划为MySQL内部优化器通过计算耗费等分析后,所选择其认为最优的一种sql执行步骤或者信息。
用途
通过查看执行计划,可以识别出SQL语句中的表连接、执行顺序以及索引使用情况等,从而调整低效SQL写法,从而提升SQL执行性能。执行计划可以看出如下信息,以便我们进行sql调整,是进行sql优化的一个比较好的工具以及依据。
- 查看表连接顺序及相关信息
- 查看索引使用情况
- 查看SQL执行的排序、可能扫描的行数情况
用法
通过在SQL语句前面加上关键字EXPLAIN,进行执行,从而得到该SQL的执行信息。
explain select * from tb_book;
- EXPLAIN 适用于 SELECT、DELETE、INSERT、REPLACE 和 UPDATE 语句。
- EXPLAIN SQL语句,并不会真正执行SQL语句内容,而是显示语句的执行计划信息。
- 对于SELECT 语句,EXPLAIN会生成额外的执行计划信息,这些信息可以使用"show warnings"来查看。
EXPLAIN字段释义概览
字段 | 解释 |
---|---|
id | SELECT查询标识。数值型,用来表示SQL语句中片段或操作表的执行顺序。数值越大越优先执行,相同则由上向下执行 |
select_type | select子句查询的类型。标识查询类别的归属是简单查询、主要查询、联合查询、子查询等其中的类型。常见主要有下面几种类型。SIMPLE、PRIMARY、UNION、 UNION RESULT、SUBQUERY、DERIVED |
table | 输出结果行的表/当前访问的表。有可能是其它查询表的联合结果或某表衍生 |
partitions | 查询结果的分区。如果没有分区,值为null |
type | 查询的连接类型。性能好坏的重要指标。性能由好到差的取值为null > system > const > eq_ref > ref > range > All |
possible_keys | 可能用到的索引 |
key | 实际用到的索引 |
key_len | 用到的索引字节长度 |
ref | 如使用到索引,标识具体哪一列使用,有可能为const |
rows | 预估获取到结果需扫描的行数。如果数值巨大,可以作为考虑是否要进行优化 |
filtered | 根据表过滤条件的筛选行的百分比,即经过查询条件过滤后剩余记录条数百分比 |
Extra | 额外的信息,如Using fileSort |
本次用到的演示表的定义和数据如下:
DROP TABLE IF EXISTS `tb_author`;
CREATE TABLE `tb_author` (`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '姓名',`age` int(11) NULL DEFAULT NULL COMMENT '年龄',`gender` int(11) NOT NULL COMMENT '性别',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;INSERT INTO `tb_author` VALUES (1, '小A', 25, 1);
INSERT INTO `tb_author` VALUES (2, '小B', 32, 0);
INSERT INTO `tb_author` VALUES (3, '小C', 35, 1);
INSERT INTO `tb_author` VALUES (4, '小D', 34, 0);
INSERT INTO `tb_author` VALUES (5, '小E', 26, 0);
INSERT INTO `tb_author` VALUES (6, '小F', 24, 1);
INSERT INTO `tb_author` VALUES (7, '小G', 30, 0);
INSERT INTO `tb_author` VALUES (8, '小H', 20, 0);
INSERT INTO `tb_author` VALUES (9, '小J', 20, 1);
INSERT INTO `tb_author` VALUES (10, '小K', 32, 0);DROP TABLE IF EXISTS `tb_book`;
CREATE TABLE `tb_book` (`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,`book_type_id` bigint(20) NULL DEFAULT NULL,`author_id` bigint(20) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;INSERT INTO `tb_book` VALUES (1, '兽医', '描述1', 4, 7);
INSERT INTO `tb_book` VALUES (2, 'UX / UI设计员', '描述2', 2, 10);
INSERT INTO `tb_book` VALUES (3, 'UX / UI设计员', '描述3', 3, 3);
INSERT INTO `tb_book` VALUES (4, '饲养员', '描述4', 2, 4);
INSERT INTO `tb_book` VALUES (5, '建筑师', '描述5', 2, 4);DROP TABLE IF EXISTS `tb_boot_type`;
CREATE TABLE `tb_boot_type` (`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,`name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;INSERT INTO `tb_boot_type` VALUES (1, '童话');
INSERT INTO `tb_boot_type` VALUES (2, '哲学类');
INSERT INTO `tb_boot_type` VALUES (3, '社会科学');
INSERT INTO `tb_boot_type` VALUES (4, '政治法律');
INSERT INTO `tb_boot_type` VALUES (5, '军事科学');
id
id列,数值类型,主要用于作为SELECT查询标识,用来表示SQL语句中片段或操作表的执行顺序。数值越大越优先执行,相同则由上向下执行。如果查询是由两表联合结果,id的值可以是null,这种情况可以出现在union查询中,主要知识点如下:
-
id不同,值越大越先执行
-
id相同,执行顺序由上到下
-
一条sql中,多种id值可以同时存在,既可以相同,也可以不同,遵循上述规则先后顺序执行
-
id可以为null,通常出现于union查询,最后执行
示例:
EXPLAIN
SELECTa.NAME AS bookName,( SELECT NAME FROM tb_boot_type WHERE id = 1 ) AS bookType
FROM( SELECT * FROM tb_book b ) a
WHEREa.author_id IN ( SELECT au.id FROM tb_author au WHERE au.NAME = '小D' );
如果您的版本没有显示<derived3>这一行结果,是因为在MySQL5.7之后,对衍生结果表默认进行了合并,导致不显示该条记录。
可以在对应的查询窗口执行如下sql,关闭对于衍生结果表的合并。
set session optimizer_switch='derived_merge=off';
根据执行计划的id,我们可以分析出SQL内部的各子句的执行顺序如下:
- id最大的最优先执行。id值为3的先执行,则标号为1的将被先执行,接着id值为2,图中标号为2的将被执行。具体识别可以通过table这一列判断具体执行的sql片段或表。
- 存在id值相同均为1的,则先执行上面的语句,即图中标号3,最后再执行整个外层查询。
- id值为null的情况示例
explain
select a.name
from tb_book a
union
select b.name
from tb_book b
select_type
查询类型,主要标识出各SQL片段或SELECT子句的类型是归属简单查询、子查询、联合查询等。
常见取值为:
查询类型 | 释义 |
---|---|
SIMPLE | 简单查询,查询语句中不包含子查询或UNION查询 |
PRIMARY | 最外层的查询,当出现复杂查询或者多种不同类型的查询时,最外层的查询片段 |
SUBQUERY | from前面的子查询或where条件后的子查询 |
UNION | UNION查询中,第二个查询SQL片段或后面的SQL查询片段 |
UNION RESULT | UNION的结果 |
DERIVED | 衍生表。from后的子查询,该子查询结果作为其他查询使用 |
相对少见的取值:
查询类型 | 释义 |
---|---|
DEPENDENT UNION | UNION查询中依赖外部查询的第二个查询SQL片段或后面的SQL查询片段 |
DEPENDENT SUBQUERY | 依赖外部查询下的子查询 |
DEPENDENT DERIVED | 依赖于另一个表的衍生表 |
MATERIALIZED | 实体化子查询 |
UNCACHEABLE SUBQUERY | 不能缓存结果的子查询,必须为外部查询的每一行重新计算 |
UNCACHEABLE UNION | UNION查询中第二个查询SQL,属于UNCACHEABLE SUBQUERY |
常见的内容示例
- SIMPLE
简单查询,查询语句中不包含子查询或UNION查询。
EXPLAIN SELECT * FROM tb_book;
- PRIMARY
最外层的查询,当出现复杂查询或者多种不同类型的查询时,最外层的查询片段。
EXPLAIN SELECT b.* FROM ( SELECT a.* FROM tb_book as a ) AS b;
- SUBQUERY
from前面的子查询
EXPLAIN
SELECTa.NAME,( SELECT b.id FROM tb_boot_type b WHERE id = 2 ) AS typeId
FROMtb_book a
where 后面的子查询
EXPLAIN
SELECT id,NAME
FROM tb_book
where book_type_id = (SELECT id FROM tb_boot_type where id = 1)
对比写在后面作为条件的查询SQL,我们平时也称为子查询,有着不一样的查询类型标识 。
1.子查询sql作为in内部语句使用。
作为in的内部子查询片段,SQL执行计划查询类型不是SUBQUERY,而是SIMPLE(这个取决于查询片段的SQL的复杂程度)
EXPLAIN
SELECT a.name
FROM tb_book a
WHERE a.book_type_id in ( SELECT b.id from tb_boot_type b where id = 2 )
2.子查询sql作为exist内部语句使用。
举例的情况下的查询类型为DEPENDENT SUBQUERY,依赖到了外部的查询条件。
EXPLAIN
SELECTa.name
FROM tb_book a
WHERE EXISTS (SELECT 1 from tb_boot_type b where a.book_type_id = b.id and b.id = 2 )
- UNION 和 UNION RESULT
union指的是使用到union查询的第二部分的查询SQL(即例子中的 SELECT b.id,b.name from tb_book b where b.id =2
)
UNION RESULT 是union合并的结果。此处为SELECT a.id,a.name FROM tb_book a where a.id =1
和 SELECT b.id,b.name from tb_book b where b.id =2
explain
SELECT a.id,a.name FROM tb_book a where a.id =1
union
SELECT b.id,b.name from tb_book b where b.id =2
- DERIVED
衍生表。from后的子查询,该子查询结果作为其他查询使用。
EXPLAIN SELECT b.name from (SELECT a.id,a.name FROM tb_book a) b
这里例子中 SELECT a.id,a.name FROM tb_book a
的查询类型即被标为DERIVED。
table
输出结果行的表/当前访问的表。
用于通过这个字段识别出当前查询的SQL查询的是哪一张表的数据。主要有以下三点可以留意:
-
标识当前SQL查询结果的表
-
默认情况下会显示表的名称,如果SQL查询的表存在别名,则table的取值为表的别名。实际当不设置表名称时,表名即为表的别名。
-
该值可以是衍生表
<derivedN>
、联合查询结果表<unionM,N>
、子查询结果表<subqueryN>
。3.1 衍生表。值为
<derivedN>
,其中N是个id列的值,表示该衍生表结果来源于哪一个查询。3.2 联合查询结果表。值
<unionM,N>
,其中M、N是id列的值,表示来源于哪两个查询的id的结果合并。3.3 子查询结果表。值为
<subqueryN>
,其中N是id列的值,表示来源于哪个查询。
关于1,2两点的示例:
EXPLAIN SELECT name FROM tb_book;
EXPLAIN SELECT a.name FROM tb_book a;
- 衍生表
EXPLAIN SELECT a.name FROM (SELECT b.id,b.name from tb_book b) a;
可以看到,即使给外层取了别名a,实际并没有生效,而是使用到衍生表的命名方式<derived2>
,其中数值2,表示来自于id为2的查询标识结果。
- union查询
explain
SELECT a.id,a.name FROM tb_book a where a.id =1
union
SELECT b.id,b.name from tb_book b where b.id =2
id为null的这一条的table为<union1,2>
,其中1,2表示的是来源于id是1和2的查询结果的合并的结果表。
partitions
查询结果的分区。如果没有分区或不是分区表,则该值为null。
type
查询的连接类型。这个字段的值是用来判断SQL查询性能优劣非常重要的一个指标。
type的值可以存在以下内容,性能由好到差的值顺序相同,最好的在写在最前面,完整的取值性能如下:
NULL > system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
实际我们只需记忆到的性能为:
NULL > system > const > eq_ref > ref > range > index > ALL
要求达到range及其以上级别。
下面对取值进行具体的描述。
- null
不需要访问表的记录,也不需要遍历索引,直接从索引树找到并返回结果。
- 直接使用聚合函数取主键,如查最大id或最小id。这种情况下直接通过索引获取到数据,且不需要对索引进行扫描。
EXPLAIN SELECT min(id) FROM tb_book;
2. 对于不可能出现的sql场景,直接返回结果。
如查询name同时为1和2的数据,是不可能满足的查询条件场景,type的值也是null。
explain SELECT * FROM tb_book where name ='1' and name ='2';
- system
查询的表只有一行记录(相当于系统表),这是const类型的特例。这种查询情况,不是说物理表只有一行数据就会达到system级别,而是更多是的作为子查询的情况下才达到,极其特殊的场景。
之所以说是const的特例,是因为
EXPLAIN SELECT a.* FROM (SELECT * from tb_book LIMIT 0,1) a ;
- const
查询的表的结果中最多存在一条记录。
存在以下两种情况,可以使得查询到达const级别。
- 主键。指定某个主键进行查询,主键是唯一的,所以最多匹配一条数据。
- 唯一索引。因为字段唯一,可以查询的结果也最多匹配一条数据。
由于查询通常是由主键/唯一索引与常量值进行等值比较,因为只匹配一条数据,所以const级别的查询是非常快的。
EXPLAIN SELECT * FROM tb_book WHERE id = 1
- eq_ref
- 唯一性索引扫描,最多只有一条记录与之匹配。
- 进行表关联查询时,该表的关联列是主键索引或唯一非空索引进行的查询时,表现为eq_ref,常见于
=
匹配的索引列上。
例如对于下面的2个例子sql,ref_table用主键列进行关联查询,ref_table所在的执行计划信息的type表现为eq_ref。
SELECT * FROM ref_table,other_tableWHERE ref_table.key_column=other_table.column;SELECT * FROM ref_table,other_tableWHERE ref_table.key_column_part1=other_table.columnAND ref_table.key_column_part2=1;
实际举例:tb_book的author_id没有创建索引,所以type是ALL,创建完索引,type为index。
EXPLAIN
SELECT a.id "authorID",b.author_id
FROM tb_book b
LEFT JOIN tb_author a on a.id = b.author_id
- ref
- 非唯一性索引扫描,返回所有匹配某个单独值的所有行记录。
- 常见于联合索引的最左匹配索引、非主键索引、非唯一索引进行连接匹配查询,使用
=
和<>
匹配的条件下。
新建一个表tb_author_other,插入一些示例数据:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for tb_author_other
-- ----------------------------
DROP TABLE IF EXISTS `tb_author_other`;
CREATE TABLE `tb_author_other` (`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,`author_id` bigint(20) NULL DEFAULT NULL,`author_info` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '作者其他信息',PRIMARY KEY (`id`) USING BTREE,INDEX `idx_author`(`author_id` ASC) USING BTREE,INDEX `idx_author_info`(`author_info` ASC) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of tb_author_other
-- ----------------------------
INSERT INTO `tb_author_other` VALUES (1, 4, '其他信息4');
INSERT INTO `tb_author_other` VALUES (2, 5, '其他信息5');
INSERT INTO `tb_author_other` VALUES (3, 7, '其他信息7');SET FOREIGN_KEY_CHECKS = 1;
- 普通索引列的等值查询的情况
给表添加一个普通索引
--创建索引
ALTER TABLE tb_author_other ADD INDEX idx_author_info(author_info);
--查看执行计划
EXPLAIN SELECT * FROM tb_author_other where author_info = '其他信息4';
2.表关联查询
在表需要进行关联查询的列上,创建一个普通索引,并与其他表进行关联查询。
--创建普通索引
ALTER TABLE tb_author_other ADD INDEX idx_author(author_id);
--查看执行计划
EXPLAIN
SELECT b.*
FROM tb_book b
LEFT JOIN tb_author_other ao on ao.author_id=b.author_id
如果给tb_book的author_id创建索引且不是b.*的情况下,b表的type的值将为 index
- fulltext
使用全文索引执行连接。
- ref_or_null
该连接类型类似于ref,但多加入了NULL值查询,MySQL会对包含NULL值的行进行额外的搜索。这种连接类型优化通常用于解析子查询。
在下面的例子中,MySQL可以使用ref_or_null连接来处理tb_author_other。
EXPLAIN
SELECT * FROM tb_author_other where author_info = '其他信息4' or author_info is NULL;
- index_merge
此连接类型表示使用了索引合并优化。在这种情况下,输出行中的key列显示用到的索引集。
表tb_author_other存在两列普通索引author_id、author_info,使用这两列进行查询。
EXPLAIN SELECT * FROM tb_author_other where author_id=4 or author_info='其他信息4'
官网举例如下index_merge的场景。tbl_name为表名,key1、key2 这种是索引列。
SELECT * FROM tbl_name WHERE key1 = 10 OR key2 = 20;SELECT * FROM tbl_nameWHERE (key1 = 10 OR key2 = 20) AND non_key = 30;SELECT * FROM t1, t2WHERE (t1.key1 IN (1,2) OR t1.key2 LIKE 'value%')AND t2.key1 = t1.some_col;SELECT * FROM t1, t2WHERE t1.key1 = 1AND (t2.key1 = t1.some_col OR t2.key2 = t1.some_col2);
- unique_subquery
此类型替换了以下形式的IN
子查询的eq_ref
:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery只是一个索引查找函数,它完全替换子查询以提高效率。
- index_subquery
这种类型与unique_subquery
相似,作用在非唯一索引上。
value IN (SELECT key_column FROM single_table WHERE some_expr)
- range
索引范围扫描。只检索在给定范围内的行,并使用索引来选择这些行。
- range会出现在当索引列用到比较操作符时,如
=
,<>
,>
,>=
,<
,<=
,IS NULL
,<=>
,BETWEEN
,LIKE
, 或IN()
。 - 不需要扫描全部的索引,开始于索引的某一点,终止于索引的另一点。
- 当type列值为range时,ref的列的值为NULL,key会显示所使用到的索引。
使用到range的官网示例如下,key_前缀表示该列是索引列:
SELECT * FROM tbl_nameWHERE key_column = 10;SELECT * FROM tbl_nameWHERE key_column BETWEEN 10 and 20;SELECT * FROM tbl_nameWHERE key_column IN (10,20,30);SELECT * FROM tbl_nameWHERE key_part1 = 10 AND key_part2 IN (10,20,30);
- index
索引扫描。index
和ALL
情形相似,只是index扫描的是索引树。index出现在下面两种情况。
- 如果该索引是查询的覆盖索引,并且可以用于满足表中所需的所有数据,则只扫描该索引树。在这种情况下,
Extra
的值为Using index
。仅进行索引的扫描通常比ALL更快,因为索引的大小通常小于表数据。 - 利用索引进行排序/分组,也可以使用到index连接类型。
给tb_book的author_id创建了普通索引。
示例1 SELECT author_id FROM tb_book;示例2 SELECT id,author_id FROM tb_book order by author_id;示例3 SELECT author_id,count(*) FROM tb_book group by author_id;
如果示例1,2,3额外取了一些不是索引树上可以取到的列,type类型将为ALL
。如示例1中,select查询字段多增加name
列,导致回表,查询数据耗时。
- ALL
全表扫描,会扫描表里所有的数据来找到符合条件的数据。这种情况下,是非常建议进行对sql进行优化的。
possible_keys
可能使用到的索引。可能使用到的索引可以不止一个。
- 如果possible_keys为NULL,可能所使用的
WHERE
子句的字段没有加索引,可以考虑加上索引 - 覆盖索引情况possible_keys会为NULL,但实际上会走索引,只是没有在possible_keys显示
- 如果不为null,但是实际上又没有用到索引,可以考虑是否因为查询条件的写法导致索引失效
key
实际使用到的索引。该列可以显示出当前查询使用到的具体索引。
-
key
为NULL,表示没有使用到索引 -
对于InnoDB,即使查询也选择了主键,辅助索引也可能覆盖所选的列,因为InnoDB对每个辅助索引都存储了主键值
-
key
这一列的取值不一定来自于possible_keys
中的其中一个,当possible_keys
为NULL
时,实际也有可能走索引,即key
有值。例如覆盖索引的情况 -
索引最大长度是768字节,当超过该长度时,会进行截取
EXPLAIN SELECT author_id FROM tb_book;
key_len
索引中使用的字节数。key_len
是索引列的最大长度,不是列的实际长度。主要用于判断联合索引的使用情况。
key_len
的值越小,索引效果越好。联合索引的情况下,值越大,说明使用到的索引越充分key_len
可以用来判断联合索引的使用程度- 由于存储方式不一样,允许为null的索引比相同类型的索引的字节长度+1
key_len长度计算:
类型 | 长度(字节) | 备注 |
---|---|---|
tinyint | 1 | |
smallint | 2 | |
int | 4 | |
bigint | 8 | |
char(n) | gbk 2n; utf8 3n;utf8mb4 4n | 依据编码决定 |
varchar(n) | gbk 2n+2; utf8 3n+2;utf8mb4 4n+2 | 依据编码决定,相比char多2字节 |
date | 3 | |
timestamp | 4 | |
datetime | 8 |
给tb_author 创建name、age的联合索引,其中name的字段为varchar(32) 用的是utfmb4编码,age为int类型,均可为NULL。
- 只使用name字段进行条件过滤时,key_len值为 131:
name为varchar(32)且为utf8mb4编码,则可得:32*4+2=130
name字段可以为NULL,存储需要多1字节,则:130+1 = 131
- 同时使用name和age字段条件过滤时,key_len为136:
前面name的场景是不变的,使用到name的长度,并且此时age字段为int类型,则131(name字段)+4(类型存储)=135;而age字段也是可以为NULL,则+1字节为136。
ref
ref列显示将哪些列或常量与索引列进行比较。
如果该值为func,则所使用的值是某个函数的结果。
rows
MySQL执行该查询所需要读取的行数。
- 该值不能最终返回结果的记录数,是预估要返回所需结果需要读取的行数
- 如果该值十分巨大,该值对优化有一定参考性
- 对于
InnoDB
的表,该值是粗略的数据,并不一定是十分准确的
filtered
通过查询条件过滤后的记录数所占的百分比。该值也不一定是十分准确的。
- 最大值为100,意味着没有需要过滤的数据,查出来的结果数和扫描的结果数一致
- 预估数
*
百分比(rows
*filtered
)为当前查询的结果条数 filtered
的比例越高,查找目标数据所扫描的多余的数据就越少,所以占比越高越好。
Extra
其他额外的信息描述。
需要重点关注Using filesort
和Using temporary
两个取值,对性能的影响是较大的!其中MySQL官方文档中描述,当需要查询尽可能快的时,需要关注Using filesort
和Using temporary
的查询,尽量对其进行优化。
下面列举较为常见的取值:
- Using filesort
文件排序(MySQL没办法利用索引完成的排序,称为"文件排序")。这种情况下,MySQL需要做额外的传递来用给定顺序检索行。性能效率低。
EXPLAIN SELECT * FROM tb_book order by name
- Using temporary
使用临时表。为了处理查询,MySQL需要使用到临时表去存放结果。性能效率低。
Using temporary的场景通常发生在使用group by或order by语句中。
EXPLAIN SELECT name,count(*) FROM tb_book group by name
取值 | 释义 |
---|---|
Using index | 查询使用到了覆盖索引 |
Using index condition | 查询的列不完全被索引覆盖,where条件中是一个前导列的范围 |
Using where | 使用where条件过滤 |
Backward index scan | InnoDB 表中优化器可以反向索引顺序查找。和Using index一起显示 |
Impossible WHERE | WHERE 条件总为false,即条件不成立 |
Select tables optimized away | 使用聚合函数操作索引字段 |
参考文档/视频:
1.MySQL官方文档 .0/en/
2.MySQL原理及优化 =26
3.尚硅谷MySQL数据库高级,mysql优化,数据库优化 =333.788.top_right_bar_window_custom_collection.content.click
4.MySQL高级进阶课程-全套(配源码+笔记+文档+素材)=333.999.0.0
5.SQL优化-面试必备之Sql调优 =19
更多推荐
一文读懂MySQL执行计划 Explain
发布评论