且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

实战讲解MySQL的expain执行计划,面试官当场要了我(上)

更新时间:2022-09-19 10:35:03

explain或者desc获取MySQL如何执行select语句的信息。

实战讲解MySQL的expain执行计划,面试官当场要了我(上)

结果包含很多列

1 各列字段说明

1.1 id

SELECT标识符。这是查询中SELECT的序列号,表示查询中执行select子句或者操作表的顺序。如果该行引用其他行的并集结果,则该值可为NULL。

id号分为三种情况:

  1. id相同,那么执行顺序从上到下
explain se1ect * from emp e join dept d on e.deptno = d.deptno 
    join salgrade sg on e.sa1 between sg.1osal and sg.hisal;
  1. id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
explain select * from emp e where e.deptno in 
    (select d.deptno from dept d where d.dname = 'SALES');
  1. id相同和不同的,同时存在:相同的可以认为是一组,从上往下顺序执行,在所有组中,id值越大, 越先执行
exp1ain select * from emp e join dept d on e.deptno = d.deptno join salgrade sg on e.sa1
between sg.1osal and sg.hisal where e. deptno in (select d.deptno from dept d where
d.dname = 'SALES');
select_ type

1.2 select_type

区分SELECT的类型,是普通查询还是联合查询还是子查询:

  • simple(简单表,不用表连接或子查询)
  • primary(主查询,外部查询)
  • union(union中的第二个或者后面的查询语句)
  • subquery(子查询中的第一个select)

1.3 table

输出结果集。对应行正在访问哪个表,表名或者别名,可能是临时表或者union合并结果集。


如果是具体表名,则表明从实际的物理表中获取数据,当然也可是表的别名

表名是derivedN的形式,表示使用了id为N的查询产生的衍生表

当有union result时,表名是union n1,n2等的形式,n1,n2表示参与union的id

1.4 type

type列描述如何连接表。

表示MySQL在表中找到所需行的方式,或者叫访问类型

常见类型:all,index,range,ref,eq_ref,const,system,null,性能由差到好。

一般需要保证查询至少达到range级,***能达到ref。

1.4.1 ALL

最简单暴力的全表扫描,MySQL遍历全表找到匹配行,效率最差。

对来自先前表的行的每个组合进行全表扫描。若该表是未标记为const的第一个表,则通常不好,并且在所有其他情况下通常性能也非常糟糕。

一般可以通过增加索引来避免ALL,这些索引允许基于早期表中的常量值或列值从表中检索行。

explain select * from film where rating > 9;

1.4.2 index

连接类型与ALL相同,除了扫描索引树外。这发生于两种方式:

  1. 若索引是查询的覆盖索引,并且可用于满足表中所需的所有数据,则仅扫描索引树
    这种情况下,Extra列显示Using index。仅索引扫描通常比ALL更快,因索引大小通常小于表数据
  2. 使用对索引的读取执行全表扫描,以按索引顺序查找数据行。Extra列不显示 Using index

当查询仅使用属于单个索引一部分的列时,MySQL可以使用此连接类型。

explain select title from film;

1.4.3 range

使用索引查询行,仅检索给定范围内的行。

key列指示使用的哪个索引。key_len包含使用的最长的键部分。

此类型的ref=NULL

实战讲解MySQL的expain执行计划,面试官当场要了我(上)

当使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, LIKE, or IN()操作符将key列与常量进行比较时,可以使用range:

索引范围扫描,常见<,<=,>,>=,between

SELECT * FROM tbl_name
  WHERE key_column = 10;

SELECT * FROM tbl_name
  WHERE key_column BETWEEN 10 and 20;

SELECT * FROM tbl_name
  WHERE key_column IN (10,20,30);

SELECT * FROM tbl_name
  WHERE key_part1 = 10 AND key_part2 IN (10,20,30);

1.4.4 index_subquery

此连接类型类似于unique_subquery。它代替了IN子查询,但适用于以下形式的子查询中的非唯一索引:

value IN (SELECT key_column FROM single_table WHERE some_expr)

1.4.5 unique_subquery

此类型将eq_ref替换为以下形式的某些IN子查询:

value IN (SELECT primary_key FROM single_table WHERE some_expr)

unique_subquery只是一个索引查找函数,可以完全替换子查询以提高效率。