MySQL性能问题

查询执行计划

explain + sql语句

explan select from tb ;

MySQL性能问题_第1张图片
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') ;
  • id:编号

id值相同时:从上往下,顺序执行;表的执行顺序,因数量的个数的改变而改变的原因是笛卡尔积;数据小的表,优先查询
MySQL性能问题_第2张图片
id值不同时:id值越大越优先查询(本质:在嵌套子查询时,先查内层,在查外层)
MySQL性能问题_第3张图片
id值有相同,又有不同: id值越大越优先;id值相同,从上往下 顺序执行
MySQL性能问题_第4张图片

  • select_type:查询类型
    PRIMARY:包含子查询SQL中的 主查询 (最外层)
    SUBQUERY:包含子查询SQL中的 子查询 (非最外层)
    simple:简单查询(不包含子查询、union)
    derived:衍生查询(使用到了临时表)
    a:在from子查询中只有一张表
    MySQL性能问题_第5张图片
    b:在from子查询中, 如果有table1 union table2 ,则table1 就是derived,table2就是union
    MySQL性能问题_第6张图片
    union:上例
    union result :告知开发人员,那些表之间存在union查询
  • type:类型

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

常用到的有:

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 ;

执行的结果如下:
MySQL性能问题_第7张图片
const:仅仅能查到一条数据的SQL ,用于Primary key 或unique索引 (类型 与索引类型有关)

explain select tid from test01 where tid =1 ;

MySQL性能问题_第8张图片
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) ;

MySQL性能问题_第9张图片
以上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';

MySQL性能问题_第10张图片
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 ;

MySQL性能问题_第11张图片
index:查询全部索引中数据
tid 是索引, 只需要扫描索引表,不需要所有表中的所有数据
MySQL性能问题_第12张图片
all:查询全部表中的数据
cid不是索引,需要全表所有,即需要所有表中的所有数据
MySQL性能问题_第13张图片

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

  • possible_keys :可能用到的索引,是一种预测,不准。
alter table  course add index cname_index (cname);

MySQL性能问题_第14张图片
如果 possible_key/key是NULL,则说明没用索引
MySQL性能问题_第15张图片

  • key :实际使用到的索引
  • key_len :索引的长度 ;
    作用:用于判断复合索引是否被完全使用 (a,b,c)。
create table test_kl
(
	name char(20) not null default ''
);
alter table test_kl add index index_name(name) ;

utf8:1个字符3个字节
gbk:1个字符2个字节
latin:1个字符1个字节
MySQL性能问题_第16张图片
如果索引字段可以为Null,则会使用1个字节用于标识。

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

MySQL性能问题_第17张图片

  • rows: 被索引优化查询的 数据个数 (实际通过索引而查询到的 数据个数)

MySQL性能问题_第18张图片

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

小结:对于单索引, 如果排序和查找是同一个字段,则不会出现using filesort;如果排序和查找不是同一个字段,则会出现using filesort;
避免: where哪些字段,就order by那些字段2

复合索引:不能跨列(最佳左前缀)

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

(ii). using temporary:性能损耗大 ,用到了临时表。一般出现在group by 语句中。
避免:查询那些列,就根据那些列 group by .

(iii). using index :性能提升; 索引覆盖(覆盖索引)。
原因:不读取原文件,只从索引文件中获取数据 (不需要回表查询)只要使用到的列 全部都在索引中,就是索引覆盖using index
如果用到了索引覆盖(using index时),会对 possible_keys和key造成影响:
a. 如果没有where,则索引只出现在key中;
b. 如果有where,则索引 出现在key和possible_keys中。

(iiii).using where (需要回表查询)
假设age是索引列
但查询语句select age,name from …where age =…,此语句中必须回原表查Name,因此会显示using where.

(iv). impossible where : where子句永远为false

你可能感兴趣的:(MySQL)