查询执行计划: 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') ;
(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)
(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')
);
(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') ;
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 ;
system>const>eq_ref>ref>range>index>all,要对type进行优化的前提:有索引
a.system(忽略): 只有一条数据的系统表 ;或 衍生表只有一条数据的主查询
b.const:仅仅能查到一条数据的SQL,用于Primary key 或unique索引(类型与索引类型有关)
EXPLAIN
SELECT * FROM `course` WHERE cid =1
EXPLAIN
SELECT * FROM `course` WHERE tid =2
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 ;
例:teacher表中tname字段加上普通索引
EXPLAIN
SELECT * FROM teacher WHERE tname ="tl"
e.range:检索指定范围的行 ,where后面是一个范围查询(between ,> < >=, 特殊:in有时候会失效 ,从而转为 无索引all)
EXPLAIN
SELECT * FROM teacher WHERE tcid >2;
f.index:查询全部索引中数据,只扫描了索引就查到了数据
例:teacher表中tname字段加了普通索引
EXPLAIN SELECT tname FROM teacher;
例:course表中tid无索引,全表扫描,是最慢的
EXPLAIN
SELECT tid FROM `course`
system/const: 结果只有一条数据
eq_ref:结果多条;但是每条数据是唯一的
ref:结果多条;但是每条数据是是0或多条
预测用到的索引,实际中不一定准确
用于判断复合索引是否被完全使用。
在mysql中utf8:1个字符占3个字节
以上都是单列索引,是分别在不同字段上加上索引。下面是联合索引。
作用: 指明当前表所参照的字段。注意与type中的ref值区分。
a.using filesort:性能消耗大;需要“额外”的一次排序(查询)。常见于 order by 语句中。
对于单索引, 如果排序和查找是同一个字段,则不会出现using filesort;如果排序和查找不是同一个字段,则会出现using filesort;
避免: where哪些字段,就order by那些字段
对于联合索引
避免: where和order by 按照复合索引的顺序使用,不要跨列或无序使用。
例:course表中加上cname ,cname1, cname2三个作为联合索引,使用中不能跨列(最佳左前缀)
b.using index :性能提升; 索引覆盖(覆盖索引)。原因:不读取原文件,只从索引文件中获取数据 (不需要回表查询)
只要使用到的列 全部都在索引中,就是索引覆盖using index
c.using where (需要回表查询)