Mysql——》explain执行计划

推荐链接:
    总结——》【Java】
    总结——》【Mysql】
    总结——》【Redis】
    总结——》【Kafka】
    总结——》【Spring】
    总结——》【SpringBoot】
    总结——》【MyBatis、MyBatis-Plus】
    总结——》【Linux】
    总结——》【MongoDB】
    总结——》【Elasticsearch】

Mysql——》explain执行计划

  • 一、概念
  • 二、语法
    • 1、适用SQL
    • 2、输出格式FORMAT
    • 3、示例
    • 4、测试数据
  • 三、执行计划各字段介绍
    • 1、id
      • (1)id相同:从上往下执行
      • (2)id不同:先大后小,越大越先执行
      • (3)id有相同有不同:id不同的先大后小,id相同的从上往下执行
    • 2、select_type
      • (1)SIMPLE
      • (2)PRIMARY
      • (3)UNION
      • (4)DEPENDENT UNION
      • (5)UNION RESULT
      • (6)SUBQUERY
      • (7)DEPENDENT SUBQUERY
      • (8)DERIVED
      • (9)UNCACHEABLE SUBQUERY
      • (10)UNCACHEABLE UNION
    • 3、table
      • (1)表名/别名
      • (2)``
      • (3)``
    • 4、partitions
    • 5、type
      • (1)system
      • (2)const
      • (3)eq_ref
      • (4)ref
      • (5)fulltext
      • (6)ref_or_null
      • (7)index_merge
      • (8)unique_subquery
      • (9)index_subquery
      • (10)range
      • (11)index
      • (12)ALL
    • 6、possible_keys
    • 7、key
    • 8、key_len
    • 9、ref
    • 10、rows
    • 11、filtered
    • 12、extra
      • (1)using index
      • (2)using where
      • (3)using filesort
      • (4)using temporary
        • (4.1)distinct(非索引列)
        • (4.2)group by (非索引列)
      • (5)using join buffer
      • (6)Impossible WHERE
      • (7)no matching row in const table

参考链接:官网explain-output

为了知道优化SQL语句的执行,需要查看SQL语句的具体执行过程,以加快SQL语句的执行效率。可以使用explain+SQL语句来模拟优化器执行SQL查询语句,从而知道mysql是如何处理sql语句的。

一、概念

一条查询语句在经过MySQL查询优化器的各种基于成本规则优化会后生成一个执行计划,从而知道MySQL是如何处理SQL语句的。

这个执行计划展示了具体执行查询的方式

  1. 多表连接的顺序是什么
  2. 对于每个表采用什么访问方法来具体执行查询

二、语法

1、适用SQL

SELECT,DELETE,INSERT,REPLACE、UPDATE

2、输出格式FORMAT

输出格式 以哪种格式显示输出 是否默认
TRADITIONAL 表格
JSON JSON

3、示例

在SQL查询的前面加上EXPLAIN关键字

-- 普通表:以表格格式显示输出
explain select * from course;

-- 普通表:以JSON格式显示输出
explain format = json select * from course;

-- 分区表:以表格格式显示输出
explain partitions select * from course;
EXPLAIN FORMAT = json select * from student where age >=3 and age <=10 and name like '%a%';

Mysql——》explain执行计划_第1张图片

4、测试数据

-- 3张表:course、teacher、teacher_contact

DROP TABLE IF	EXISTS course;
CREATE TABLE `course` ( 
`cid` INT ( 3 ) DEFAULT NULL, 
`cname` VARCHAR ( 20 ) DEFAULT NULL, 
`tid` INT ( 3 ) DEFAULT NULL ) 
ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

DROP TABLE IF	EXISTS teacher;
CREATE TABLE `teacher` ( 
`tid` INT ( 3 ) DEFAULT NULL, 
`tname` VARCHAR ( 20 ) DEFAULT NULL, 
`tcid` INT ( 3 ) DEFAULT NULL ) 
ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

DROP TABLE IF	EXISTS teacher_contact;
CREATE TABLE `teacher_contact` ( 
`tcid` INT ( 3 ) DEFAULT NULL, 
`phone` VARCHAR ( 200 ) DEFAULT NULL 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

INSERT INTO `course` VALUES	( '1', 'mysql', '1' );
INSERT INTO `course` VALUES	( '2', 'jvm', '1' );
INSERT INTO `course` VALUES	( '3', 'juc', '2' );
INSERT INTO `course` VALUES	( '4', 'spring', '3' );

INSERT INTO `teacher` VALUES	( '1', 'bobo', '1' );
INSERT INTO `teacher` VALUES	( '2', 'jim', '2' );
INSERT INTO `teacher` VALUES	( '3', 'dahai', '3' );

INSERT INTO `teacher_contact` VALUES	( '1', '13688888888' );
INSERT INTO `teacher_contact` VALUES	( '2', '18166669999' );
INSERT INTO `teacher_contact` VALUES	( '3', '17722225555' );

三、执行计划各字段介绍

Column Meaning 中文描述
id The SELECT identifier 查询序列编号
select_type The SELECT type 查询类型
table The table for the output row 访问的表名
partitions The matching partitions 匹配的分区信息
type The join type 访问的类型
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
possible_keys The possible indexes to choose 可能用到的索引
key The index actually chosen 实际用到的索引
key_len The length of the chosen key 实际用到的索引长度(字节数)
ref The columns compared to the index 索引的哪一列被使用了
rows Estimate of rows to be examined 估算扫描的行数
filtered Percentage of rows filtered by table condition 过滤
extra Additional information 额外的信息说明

1、id

id是一组数字,是select查询序列编号,表示查询中执行select子句或者操作表的顺序,有以下3种情况:

(1)id相同:从上往下执行

-- 查询课程 ID 为 2,或者联系表 ID 为 3 的老师
EXPLAIN SELECT
	t.tname,
	c.cname,
	tc.phone 
FROM
	teacher t,
	course c,
	teacher_contact tc 
WHERE
	t.tid = c.tid 
	AND t.tcid = tc.tcid 
	AND ( c.cid = 2 OR tc.tcid = 3 );

 -- 执行顺序:t表 -> c表 -> tc表

Mysql——》explain执行计划_第2张图片

(2)id不同:先大后小,越大越先执行

Q:什么情况下,id的序号会递增?
A:包含子查询的时候

-- 查询 mysql 课程的老师手机号
EXPLAIN SELECT
	tc.phone 
FROM
	teacher_contact tc 
WHERE
	tcid = ( SELECT tcid FROM teacher t WHERE t.tid = ( SELECT c.tid FROM course c WHERE c.cname = 'mysql' ) );

-- 执行顺序:c表 -> t表 -> tc表

Mysql——》explain执行计划_第3张图片

(3)id有相同有不同:id不同的先大后小,id相同的从上往下执行

2、select_type

查询类型:普通查询 / 联合查询 / 子查询)

select_type Value Meaning 中文描述
SIMPLE Simple SELECT (not using UNION or subqueries) 简单的select查询(不包含关联查询、子查询)
PRIMARY Outermost SELECT 最外层的select查询
UNION Second or later SELECT statement in a UNION UNION 中的第二个或随后的 select 查询, 不依赖于外部查询的结果集
DEPENDENT UNION Second or later SELECT statement in a UNION, dependent on outer query UNION中的第二个或随后的SELECT语句,依赖于外部查询
UNION RESULT Result of a UNION. UNION查询的结果集
SUBQUERY First SELECT in subquery 子查询中的第一个SELECT查询,不依赖于外部查询的结果集
DEPENDENT SUBQUERY First SELECT in subquery, dependent on outer query 子查询中的第一个SELECT,依赖于外部查询的结果集
DERIVED Derived table 在FROM 中包含的子查询,被标记为 DERIVED(衍生),MYSQL会递归执行这些子查询,把结果放在临时表中
UNCACHEABLE SUBQUERY A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query 结果集不能被缓存的子查询,必须重新为外层查询的每一行进行评估
UNCACHEABLE UNION The second or later select in a UNION that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY) UNION 中的第二个或随后的 select 查询,属于不可缓存的子查询

(1)SIMPLE

简单的查询不包含以下:

  • 子查询
  • 关联查询union
EXPLAIN SELECT * FROM	teacher;

image.png

(2)PRIMARY

查询中如果包含子查询,最外层查询则被标记为PRIMARY

-- 查询 mysql 课程的老师手机号
EXPLAIN SELECT
	tc.phone 
FROM
	teacher_contact tc 
WHERE
	tcid = ( SELECT tcid FROM teacher t WHERE t.tid = ( SELECT c.tid FROM course c WHERE c.cname = 'mysql' ) );

Mysql——》explain执行计划_第4张图片

-- 查询 ID 为 1 或 2 的老师教授的课程
EXPLAIN SELECT
	cr.cname 
FROM
	( SELECT * FROM course WHERE tid = 1 UNION SELECT * FROM course WHERE tid = 2 ) cr;

Mysql——》explain执行计划_第5张图片

(3)UNION

如果select出现在union之后,则被标记为union

EXPLAIN SELECT * FROM	course WHERE tid = 1 
UNION   SELECT * FROM course WHERE tid = 2;

Mysql——》explain执行计划_第6张图片

(4)DEPENDENT UNION

(跟union类似)union或union all联合而成的结果会受外部表影响

(5)UNION RESULT

表示从UNION表获取结果
示例:代表 id=1 和 id=2 的查询存在 UNION

EXPLAIN SELECT * FROM	course WHERE tid = 1 
UNION   SELECT * FROM course WHERE tid = 2;

-- 代表 id=1 和 id=2 的查询存在 UNION

Mysql——》explain执行计划_第7张图片

(6)SUBQUERY

如果select或者where中包含子查询,则被标记为SUBQUERY

-- 查询 mysql 课程的老师手机号
EXPLAIN SELECT
	tc.phone 
FROM
	teacher_contact tc 
WHERE
	tcid = ( SELECT tcid FROM teacher t WHERE t.tid = ( SELECT c.tid FROM course c WHERE c.cname = 'mysql' ) );

Mysql——》explain执行计划_第8张图片

(7)DEPENDENT SUBQUERY

表示subquery子查询要受到外部表查询的影响

(8)DERIVED

表示在得到最终查询结果之前会用到临时表
注意:from子句中出现的子查询,叫做派生类(衍生查询)

-- 查询 ID 为 1 或 2 的老师教授的课程
EXPLAIN SELECT
	cr.cname 
FROM
	( SELECT * FROM course WHERE tid = 1 UNION SELECT * FROM course WHERE tid = 2 ) cr;

Mysql——》explain执行计划_第9张图片

(9)UNCACHEABLE SUBQUERY

表示子查询结果不能被缓存

(10)UNCACHEABLE UNION

表示union查询结果不能被缓存

3、table

表示访问哪一个表 (表名 / 别名 / 临时表 / union合并结果集)

  • :该行指的是id值为M和N的行的并集
  • :该行引用id值为N的行的派生表结果
  • :该行引用id值为N的行的具体化子查询的结果

(1)表名/别名

从实际的物理表中获取数据

(2)

示例:
表示:使用了id为2 的查询产生的衍生表
Mysql——》explain执行计划_第10张图片

(3)

示例:
表示:2 和 3 表示参与union的id (查询类型为union result)
Mysql——》explain执行计划_第11张图片

4、partitions

记录将与查询匹配的分区。对于非分区表,该值为NULL。

5、type

表示访问类型(以何种方式访问数据)

效率从最好到最坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

注意:

  1. 一般情况下,至少达到range级别,最好能达到ref
  2. ALL 和 index(查询全部索引)都需要优化。
-- 提前加上索引
ALTER TABLE course ADD PRIMARY KEY (`cid`);
ALTER TABLE course ADD INDEX `idx_tid`(`tid`);

ALTER TABLE teacher ADD PRIMARY KEY (`tid`);
ALTER TABLE teacher ADD INDEX idx_tcid (tcid);

ALTER TABLE teacher_contact ADD PRIMARY KEY (`tcid`);

(1)system

只有一条数据满足条件,这是const类型的特例,平时不会出现

EXPLAIN SELECT * FROM mysql.proxies_priv;

在这里插入图片描述

(2)const

使用主键索引 / 唯一索引,只能查到一条数据

EXPLAIN SELECT * FROM course where cid = 1;       

Mysql——》explain执行计划_第12张图片

(3)eq_ref

使用唯一性索引(primary key or unique)
注意:通常出现在多表的join查询,对于前表的每一个结果,都只能匹配到后表的一行结果

EXPLAIN select t.tcid from teacher t,teacher_contact tc where t.tcid = tc.tcid;

Mysql——》explain执行计划_第13张图片

(4)ref

使用非唯一性索引

EXPLAIN SELECT * FROM teacher where tcid = 3;

Mysql——》explain执行计划_第14张图片

(5)fulltext

(6)ref_or_null

(7)index_merge

(8)unique_subquery

使用唯一索引来关联子查询,不再扫描全表

(9)index_subquery

使用索引来关联子查询,不再扫描全表

(10)range

使用索引,在指定范围内进行查询

Q:范围查询操作符?
A:=, <>, >, >=, <, <=, IS NULL, BETWEEN, LIKE, IN()

EXPLAIN SELECT * FROM teacher t WHERE t.tid <3;
EXPLAIN SELECT * FROM teacher t WHERE t.tid BETWEEN 1 AND 2;
EXPLAIN SELECT * FROM teacher t WHERE t.tid in (1,2);

Mysql——》explain执行计划_第15张图片
Mysql——》explain执行计划_第16张图片
Mysql——》explain执行计划_第17张图片

(11)index

使用全索引扫描

Q:什么情况下会使用全索引扫描?
A:
情况1:查询是覆盖索引,需要的数据在索引中就可以索取
情况2:查询使用索引进行排序

-- 覆盖索引
EXPLAIN SELECT tid FROM teacher;
-- 索引排序
EXPLAIN SELECT * FROM teacher ORDER BY tid;

Mysql——》explain执行计划_第18张图片

Mysql——》explain执行计划_第19张图片

(12)ALL

使用全表扫描

EXPLAIN SELECT * FROM teacher;

Mysql——》explain执行计划_第20张图片

6、possible_keys

可能用到的索引,但不一定被实际使用,一个 or 多个 or 空

7、key

实际使用的索引
注意:
1)如果为空,则没有使用索引
2)如果使用了覆盖索引,则该索引和查询的select字段一样

EXPLAIN SELECT tcid FROM teacher where tcid  = 1;

在这里插入图片描述

8、key_len

索引中使用的字节数
注意:在不损失精度的情况下长度越短越好
Explain执行计划key_len详解
Mysql——》explain执行计划_第21张图片

9、ref

显示索引的哪一列被使用了,如果可能的话,是一个常数

explain select * from emp,dept where emp.deptno = dept.deptno and emp.deptno = 10;

10、rows

MySQL 认为扫描多少行才能返回请求的数据,是一个预估值
注意:一般来说行数越少越好

explain select * from emp;

11、filtered

查询优化器预测有多少条记录满⾜其余的搜索条件
示例:c为驱动表,t为被驱动表,驱动表的扇出值为4 * 33.33% = 1.32,说明还要对被驱动表执行2次查询

EXPLAIN SELECT * FROM	course c
	LEFT JOIN teacher t ON c.tid = t.tid 
WHERE
	c.cname > 'mysql';																																

Mysql——》explain执行计划_第22张图片

12、extra

额外的信息说明

(1)using index

覆盖索引(直接从索引中读取数据,不需要回表)

EXPLAIN SELECT tcid FROM teacher where tcid  = 1;

在这里插入图片描述

(2)using where

使用where进行条件过滤,表示存储引擎返回的记录并不是所有的都满足查询条件,需要在 server 层进行过滤(跟是否使用索引没有关系)

EXPLAIN SELECT * FROM teacher where tname = 'bobo';

在这里插入图片描述

(3)using filesort

无法使用索引进行排序,只能利用排序算法进行排序(跟磁盘或文件没有关系),会消耗额外的位置

EXPLAIN SELECT * FROM teacher ORDER BY tname;

在这里插入图片描述

(4)using temporary

使用临时表保存中间结果,查询完成后删除临时表

(4.1)distinct(非索引列)
EXPLAIN SELECT DISTINCT(tname) FROM teacher;

在这里插入图片描述

(4.2)group by (非索引列)
EXPLAIN SELECT tname FROM teacher GROUP BY tname;

在这里插入图片描述

(5)using join buffer

(6)Impossible WHERE

代表:where语句的结果总是false

EXPLAIN select * from teacher t where 1=2;

在这里插入图片描述

(7)no matching row in const table

EXPLAIN select * from teacher t where tid = 100;

在这里插入图片描述

你可能感兴趣的:(Mysql,mysql,explain,执行计划,using,index)