一文读懂MySQL执行计划 Explain

编程入门 行业动态 更新时间:2024-10-07 12:28:23

<a href=https://www.elefans.com/category/jswz/34/1769690.html style=一文读懂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字段释义概览

字段解释
idSELECT查询标识。数值型,用来表示SQL语句中片段或操作表的执行顺序数值越大越优先执行,相同则由上向下执行
select_typeselect子句查询的类型标识查询类别的归属是简单查询、主要查询、联合查询、子查询等其中的类型。常见主要有下面几种类型。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内部的各子句的执行顺序如下:

  1. id最大的最优先执行。id值为3的先执行,则标号为1的将被先执行,接着id值为2,图中标号为2的将被执行。具体识别可以通过table这一列判断具体执行的sql片段或表。
  2. 存在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最外层的查询,当出现复杂查询或者多种不同类型的查询时,最外层的查询片段
SUBQUERYfrom前面的子查询或where条件后的子查询
UNIONUNION查询中,第二个查询SQL片段或后面的SQL查询片段
UNION RESULTUNION的结果
DERIVED衍生表。from后的子查询,该子查询结果作为其他查询使用

相对少见的取值:

查询类型释义
DEPENDENT UNIONUNION查询中依赖外部查询的第二个查询SQL片段或后面的SQL查询片段
DEPENDENT SUBQUERY依赖外部查询下的子查询
DEPENDENT DERIVED依赖于另一个表的衍生表
MATERIALIZED实体化子查询
UNCACHEABLE SUBQUERY不能缓存结果的子查询,必须为外部查询的每一行重新计算
UNCACHEABLE UNIONUNION查询中第二个查询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 =1SELECT 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查询的是哪一张表的数据。主要有以下三点可以留意:

  1. 标识当前SQL查询结果的表

  2. 默认情况下会显示表的名称,如果SQL查询的表存在别名,则table的取值为表的别名。实际当不设置表名称时,表名即为表的别名。

  3. 该值可以是衍生表<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

不需要访问表的记录,也不需要遍历索引,直接从索引树找到并返回结果。

  1. 直接使用聚合函数取主键,如查最大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级别。

  1. 主键。指定某个主键进行查询,主键是唯一的,所以最多匹配一条数据。
  2. 唯一索引。因为字段唯一,可以查询的结果也最多匹配一条数据。

由于查询通常是由主键/唯一索引与常量值进行等值比较,因为只匹配一条数据,所以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;
  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

索引范围扫描。只检索在给定范围内的行,并使用索引来选择这些行。

  1. range会出现在当索引列用到比较操作符时,如=, <>, >, >=, <,<=, IS NULL, <=>, BETWEEN, LIKE, 或 IN()
  2. 不需要扫描全部的索引,开始于索引的某一点,终止于索引的另一点。
  3. 当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

索引扫描indexALL情形相似,只是index扫描的是索引树。index出现在下面两种情况。

  1. 如果该索引是查询的覆盖索引,并且可以用于满足表中所需的所有数据,则只扫描该索引树。在这种情况下,Extra的值为Using index。仅进行索引的扫描通常比ALL更快,因为索引的大小通常小于表数据。
  2. 利用索引进行排序/分组,也可以使用到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_keysNULL时,实际也有可能走索引,即key有值。例如覆盖索引的情况

  • 索引最大长度是768字节,当超过该长度时,会进行截取

EXPLAIN SELECT author_id FROM tb_book;

key_len

索引中使用的字节数。key_len是索引列的最大长度,不是列的实际长度。主要用于判断联合索引的使用情况。

  • key_len的值越小,索引效果越好。联合索引的情况下,值越大,说明使用到的索引越充分
  • key_len可以用来判断联合索引的使用程度
  • 由于存储方式不一样,允许为null的索引比相同类型的索引的字节长度+1

key_len长度计算:

类型长度(字节)备注
tinyint1
smallint2
int4
bigint8
char(n)gbk 2n; utf8 3n;utf8mb4 4n依据编码决定
varchar(n)gbk 2n+2; utf8 3n+2;utf8mb4 4n+2依据编码决定,相比char多2字节
date3
timestamp4
datetime8

给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 scanInnoDB表中优化器可以反向索引顺序查找。和Using index一起显示
Impossible WHEREWHERE条件总为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

本文发布于:2024-02-19 18:53:25,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1765477.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:一文   读懂   计划   MySQL   Explain

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!