SQL语句explain获取的查询执行计划

在sql语句前加explain查看执行计划

explain +SQL语句    

SQL语句explain获取的查询执行计划

 例子:       explain  select  * from tb ;

 

(1)id: id值相同,从上往下 顺序执行。  t3-tc3-c4

                  tc3--c4-t6

表的执行顺序  因数量的个数改变而改变的原因: 笛卡儿积

        a      b       c
        4    3     2   =              2*3=6 * 4   =24
                                3*4=12* 2   =24
数据小的表 优先查询;

id值不同:id值越大越优先查询 (本质:在嵌套子查询时,先查内层 再查外层)

查询教授SQL课程的老师的描述(desc)
explain select tc.tcdesc from teacherCard tc,course c,teacher t where c.tid = t.tid
and t.tcid = tc.tcid and c.cname = 'sql' ;

将以上 多表查询 转为子查询形式:

explain select tc.tcdesc 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')
);

子查询+多表: 
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') ;


id值有相同,又有不同: id值越大越优先;id值相同,从上往下 顺序执行

(2)select_type:查询类型
PRIMARY:包含子查询SQL中的 主查询 (最外层)
SUBQUERY:包含子查询SQL中的 子查询 (非最外层)
simple:简单查询(不包含子查询、union)
derived:衍生查询(使用到了临时表)
    a.在from子查询中只有一张表
        explain select  cr.cname     from ( select * from course where tid in (1,2) ) cr ;

    b.在from子查询中, 如果有table1 union table2 ,则table1 就是derived,table2就是union
        explain select  cr.cname     from ( select * from course where tid = 1  union select * from course where tid = 2 ) cr ;

SQL语句explain获取的查询执行计划


(4)possible_keys :可能用到的索引,是一种预测,不准。

alter table  course add index cname_index (cname);

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') ;


如果 possible_key/key是NULL,则说明没用索引


explain select tc.tcdesc from teacherCard tc,course c,teacher t where c.tid = t.tid
and t.tcid = tc.tcid and c.cname = 'sql' ;


(5) key :实际使用到的索引


(6)key_len :索引的长度 ;
    作用:用于判断复合索引是否被完全使用  (a,b,c)。
create table test_kl
(
    name char(20) not null default ''
);
alter table test_kl add index index_name(name) ;
explain select * from test_kl where name ='' ;   -- key_len :60
在utf8:1个字符站3个字节  

alter table test_kl add column name1 char(20) ;  --name1可以为null

alter table test_kl add index index_name1(name1) ;
explain select * from test_kl where name1 ='' ; 
--如果索引字段可以为Null,则会使用1个字节用于标识。

drop index index_name on test_kl ;
drop index index_name1 on test_kl ;

增加一个复合索引 
alter table test_kl add index name_name1_index (name,name1) ; 

explain select * from test_kl where name1 = '' ; --121
explain select * from test_kl where name = '' ; --60


varchar(20)
alter table test_kl add column name2 varchar(20) ; --可以为Null 
alter table test_kl add index name2_index (name2) ;

explain select * from test_kl where name2 = '' ;  --63
20*3=60 +  1(null)  +2(用2个字节 标识可变长度)  =63

utf8:1个字符3个字节
gbk:1个字符2个字节
latin:1个字符1个字节

(7) ref : 注意与type中的ref值区分。
    作用: 指明当前表所 参照的 字段。
        select ....where a.c = b.x ;(其中b.x可以是常量,const)

alter table course  add index tid_index (tid) ;

    explain select * from course c,teacher t where c.tid = t.tid  and t.tname ='tw' ;


(8)rows: 被索引优化查询的 数据个数 (实际通过索引而查询到的 数据个数)
    explain select * from course c,teacher t  where c.tid = t.tid
    and t.tname = 'tz' ;


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

10个人 根据年龄排序。

union:上例
union result :告知开发人员,那些表之间存在union查询
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

(3)type:索引类型、类型
    system>const>eq_ref>ref>range>index>all   ,要对type进行优化的前提:有索引

其中:system,const只是理想情况;实际能达到 ref>range

system(忽略): 只有一条数据的系统表 ;或 衍生表只有一条数据的主查询
    
create table test01
(
    tid int(3),
    tname varchar(20)
);

insert into test01 values(1,'a') ;
commit;
增加索引
alter table test01 add constraint tid_pk primary key(tid) ;
explain select * from (select * from test01 )t where tid =1 ;

const:仅仅能查到一条数据的SQL ,用于Primary key 或unique索引  (类型 与索引类型有关)
explain select tid from test01 where tid =1 ;
alter table test01 drop primary key ;
create index test01_index on test01(tid) ;

eq_ref:唯一性索引:对于每个索引键的查询,返回匹配唯一行数据(有且只有1个,不能多 、不能0)
select ... from ..where name = ... .常见于唯一索引 和主键索引。

 alter table teacherCard add constraint pk_tcid primary key(tcid);
alter table teacher add constraint uk_tcid unique index(tcid) ;


explain select t.tcid from teacher t,teacherCard tc where t.tcid = tc.tcid ;

以上SQL,用到的索引是 t.tcid,即teacher表中的tcid字段;
如果teacher表的数据个数 和 连接查询的数据个数一致(都是3条数据),则有可能满足eq_ref级别;否则无法满足。


ref:非唯一性索引,对于每个索引键的查询,返回匹配的所有行(0,多)
准备数据:
 insert into teacher values(4,'tz',4) ;
 insert into teacherCard values(4,'tz222');

测试:
alter table teacher add index index_name (tname) ;
explain select * from teacher     where tname = 'tz';


range:检索指定范围的行 ,where后面是一个范围查询(between   ,> < >=,     特殊:in有时候会失效 ,从而转为 无索引all)
alter table teacher add index tid_index (tid) ;
explain select t.* from teacher t where t.tid in (1,2) ;
explain select t.* from teacher t where t.tid <3 ;

index:查询全部索引中数据
explain select tid from teacher ; --tid 是索引, 只需要扫描索引表,不需要所有表中的所有数据


all:查询全部表中的数据
explain select cid from course ;  --cid不是索引,需要全表所有,即需要所有表中的所有数据


system/const: 结果只有一条数据
eq_ref:结果多条;但是每条数据是唯一的 ;
ref:结果多条;但是每条数据是是0或多条 ;