mysql 执行计划详解(附实例)

mysql 执行计划详解

执行计划

查询执行计划: explain +SQL语句

id : 编号
select_type :查询类型
table :表
type :类型
possible_keys :预测用到的索引
key :实际使用的索引
key_len :实际使用索引的长度
ref :表之间的引用
rows :通过索引查询到的数据量
Extra :额外的信息

准备数据:
create table course
(cid int(3),
cname varchar(20),
tid int(3));
create table teacher
(tid int(3),
tname varchar(20),
tcid int(3));

create table teacherCard
(tcid int(3),
tcdesc varchar(200));

insert into course values(1,'java',1);
insert into course values(2,'html',1);
insert into course values(3,'sql',2);
insert into course values(4,'web',3);

insert into teacher values(1,'tz',1);
insert into teacher values(2,'tw',2);
insert into teacher values(3,'tl',3);

insert into teacherCard values(1,'tzdesc') ;
insert into teacherCard values(2,'twdesc') ;
insert into teacherCard values(3,'tldesc') ;

mysql 执行计划详解(附实例)_第1张图片

1.id 编号

(1)id: id值相同,从上往下 顺序执行。从下图可以看到id是一样的,都是1,那么执行顺序是从上到下执行的,表的执行顺序,小表先执行,大表后执行。t表的数据最少,c表的数据最多。所以顺序是t-tc-c

例:查询课程编号为2 或 教师证编号为3 的老师信息

EXPLAIN
SELECT t.* FROM 
course AS c,
teacher AS t,
teachercard AS tc
WHERE t.tcid = tc.tcid
AND t.tid = c.tid
AND (tc.`tcid` = 3  OR c.`cid`=2)

mysql 执行计划详解(附实例)_第2张图片
(2)id值不同:id值越大越优先查询 (本质:在嵌套子查询时,先查内层 再查外层),从下图可以看到id是1,2,3,id最大的先执行

例:查询教授SQL课程的老师的描述(desc)

EXPLAIN
SELECT tc.* FROM teacherCard tc WHERE tc.tcid = 
(SELECT t.tcid FROM teacher t WHERE  t.tid =  
	(SELECT c.tid FROM course c WHERE c.cname = 'sql')
);

mysql 执行计划详解(附实例)_第3张图片
(3)id值有相同,又有不同: id值越大越优先;id值相同,从上往下 顺序执行。从下图可以看到,id=2的先执行,id是1的,按照从上往下执行,就是t-tc,总的顺序是c-t-tc

例:查询教授SQL课程的老师的描述(desc)sql语句用多表查询+子查询

EXPLAIN 
SELECT t.tname ,tc.tcdesc FROM teacher t,teacherCard tc WHERE t.tcid= tc.tcid
AND t.tid = (SELECT c.tid FROM course c WHERE cname = 'sql') ;

mysql 执行计划详解(附实例)_第4张图片

2.select_type 查询类型

PRIMARY:包含子查询SQL中的 主查询 (最外层)–见上面案例
SUBQUERY:包含子查询SQL中的 子查询 (非最外层)–见上面案例
simple:简单查询(不包含子查询、union)–见上面案例
derived:衍生查询(使用到了临时表)

例:在from子查询中, 见下图,如果有table1 union table2 ,则table1 就是derived,table2就是union。union result :告知开发人员,那些表之间存在union查询union result :告知开发人员,那些表之间存在union查询

EXPLAIN 
SELECT cr.cname 	
FROM (SELECT * FROM course WHERE tid = 1  UNION SELECT * FROM course WHERE tid = 2 ) cr ;

mysql 执行计划详解(附实例)_第5张图片

3.type 索引类型

system>const>eq_ref>ref>range>index>all,要对type进行优化的前提:有索引

a.system(忽略): 只有一条数据的系统表 ;或 衍生表只有一条数据的主查询

b.const:仅仅能查到一条数据的SQL,用于Primary key 或unique索引(类型与索引类型有关)

EXPLAIN
SELECT * FROM `course` WHERE cid =1

mysql 执行计划详解(附实例)_第6张图片

EXPLAIN
SELECT * FROM `course` WHERE tid =2

mysql 执行计划详解(附实例)_第7张图片
c.eq_ref:唯一性索引:对于每个索引键的查询,返回匹配唯一行数据(有且只有1个,不能多 、不能0)
select … from …where name = … .常见于唯一索引 和主键索引。

例:teacher表中只有3条数据,teachercard表中只有3条数据,并且一一对应

EXPLAIN 
SELECT t.tcid FROM teacher t,teacherCard tc WHERE t.tcid = tc.tcid ;

mysql 执行计划详解(附实例)_第8张图片
d.ref:非唯一性索引,对于每个索引键的查询,

例:teacher表中tname字段加上普通索引

EXPLAIN
SELECT * FROM teacher WHERE tname ="tl"

mysql 执行计划详解(附实例)_第9张图片
e.range:检索指定范围的行 ,where后面是一个范围查询(between ,> < >=, 特殊:in有时候会失效 ,从而转为 无索引all)

EXPLAIN
SELECT * FROM teacher WHERE tcid >2;

mysql 执行计划详解(附实例)_第10张图片
f.index:查询全部索引中数据,只扫描了索引就查到了数据

例:teacher表中tname字段加了普通索引

EXPLAIN SELECT tname FROM teacher; 

mysql 执行计划详解(附实例)_第11张图片
g.all:查询全部表中的数据 无索引,全表扫描

例:course表中tid无索引,全表扫描,是最慢的

EXPLAIN
SELECT tid FROM `course` 

mysql 执行计划详解(附实例)_第12张图片
system/const: 结果只有一条数据
eq_ref:结果多条;但是每条数据是唯一的
ref:结果多条;但是每条数据是是0或多条

4.possible_keys 可能用到的索引

预测用到的索引,实际中不一定准确

5.key 实际使用到的索引

6.key_len 索引的长度

用于判断复合索引是否被完全使用。

在mysql中utf8:1个字符占3个字节
mysql 执行计划详解(附实例)_第13张图片
mysql 执行计划详解(附实例)_第14张图片
mysql 执行计划详解(附实例)_第15张图片
mysql 执行计划详解(附实例)_第16张图片
mysql 执行计划详解(附实例)_第17张图片
mysql 执行计划详解(附实例)_第18张图片
以上都是单列索引,是分别在不同字段上加上索引。下面是联合索引。
mysql 执行计划详解(附实例)_第19张图片

7.ref 表之间的引用

作用: 指明当前表所参照的字段。注意与type中的ref值区分。

8.rows 通过索引查询到的数据量

9.extra 额外的信息

a.using filesort:性能消耗大;需要“额外”的一次排序(查询)。常见于 order by 语句中。

对于单索引, 如果排序和查找是同一个字段,则不会出现using filesort;如果排序和查找不是同一个字段,则会出现using filesort;
避免: where哪些字段,就order by那些字段
mysql 执行计划详解(附实例)_第20张图片
mysql 执行计划详解(附实例)_第21张图片
对于联合索引

避免: where和order by 按照复合索引的顺序使用,不要跨列或无序使用。

例:course表中加上cname ,cname1, cname2三个作为联合索引,使用中不能跨列(最佳左前缀)
mysql 执行计划详解(附实例)_第22张图片
mysql 执行计划详解(附实例)_第23张图片
mysql 执行计划详解(附实例)_第24张图片
b.using index :性能提升; 索引覆盖(覆盖索引)。原因:不读取原文件,只从索引文件中获取数据 (不需要回表查询)
只要使用到的列 全部都在索引中,就是索引覆盖using index

c.using where (需要回表查询)

d.impossible where : where子句永远为false
mysql 执行计划详解(附实例)_第25张图片

你可能感兴趣的:(mysql,mysql)