如何使用 MySQL 的 EXPLAIN 语句进行查询分析?
属性说明
explain主要用来分析SQL查询的执行计划,主要属性如下:
id:查询的执行顺序标识符,值越大优先级越高。如果是单表或没有子查询,id通常为1,;复杂查询(如包含子查询或union),id会有多个。select_type(重要):查询类型,描述查询的复杂程度。
SIMPLE:简单查询,不包含子查询或联合查询(union);PRIMARY:主查询,表示最外层的查询;SUBQUERY:子查询,表示嵌套在主查询中的查询;DERIVED:派生表,表示查询的结果被作为临时表处理;UNION:联合查询中的第二个或后续的select;UNION RESULT:联合查询结果集。
table:查询涉及的表。partitions:查询涉及的分区(仅适用于分区表)。如果表未分区,则为空;如果已经分区,则显示查询实际访问的分区列表。type(重要):访问类型。尽量避免ALL和index类型,优先使用const或eq_ref;从快到慢依次为:
system:表示查询的表只有一行数据(系统表),不常见;const:表示查询的表最多只有一行匹配结果,通常使用主键或唯一索引查询;eq_ref:表示对于每个来自前一张表的行,MySQL仅访问一次这个表。通常发生在使用主键或唯一索引进行连接查询;ref:使用非唯一索引匹配多行数据;range:使用索引范围扫描,通常出现在使用索引的范围查询中(between、>、<、>=、<=);index:全索引扫描,扫描索引中的所有行,而不是表中的所有行。即使索引列的值覆盖查询,也需扫描整个索引;ALL:全表扫描,性能最差。通常出现在没有索引的查询条件中。
possible_keys:可能使用的索引。key(重要):实际用到的索引。key_len:使用的索引长度(字节数)。长度越短,性能越好;可以判断索引是否被完全使用。ref:显示索引哪一列被使用。rows(重要):预估需要扫描的行数,数值越小,性能越好。filtered:显示查询过滤后剩余行占总行数的百分比。值越高,查询条件越有效;rows * filtered / 100 = 最终返回的行数(估算)。Extra(重要):额外信息,关于查询执行的细节:
Using index:使用了覆盖索引Using where:使用了where条件进行过滤Using temporary:使用了临时表储存中间结果Using filesort:使用了文件排序,通常需要优化Using join buffer:使用了连接缓冲区,可能需要优化Impossible WHERE:where条件永远为假,查询无结果Distinct:去重操作
例子
1)先创建一张学生作业表
CREATE TABLE `homework` (
`id` char(20) NOT NULL,
`course` varchar(255) DEFAULT NULL,
`score` int(255) DEFAULT NULL,
`level` varchar(255) DEFAULT NULL,
`teacher` varchar(255) DEFAULT NULL,
`check_time` datetime DEFAULT NULL,
`ho_fk_stu` char(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;2)查询张老师所布置的作业成绩信息,作业id、课程、成绩,并按成绩进行降序:
EXPLAIN SELECT id, course, score FROM `homework` WHERE teacher = '张老师' ORDER BY score DESC
3)简单分析,这是一个简单查询(SIMPLE),全表扫描(ALL),没有使用到索引,扫描了8205行数据,用到了where条件,使用了文件排序
4)找到问题,没有使用索引(条件和排序)
5)优化,创建联合索引
CREATE INDEX idx_teacher_score ON homework(teacher, score);6)分析优化后的结果

type:ref,使用了非唯一索引进行查询;
key:idx_teacher_score,使用该联合索引进行查询;
rows:2,预估扫描行数减少;
Extra:Using where,不再需要文件排序。
索引已经覆盖了条件和排序字段。千万注意满足最左匹配原则。
#MySQL(21)评论