MySQL(一)

原理

MySQL逻辑分层 :连接层 服务层 引擎层 存储层
在这里插入图片描述
InnoDB(默认) :事务优先 (适合高并发操作;行锁)
MyISAM :性能优先 (表锁)
查询数据库引擎: 支持哪些引擎? show engines ;
查看当前使用的引擎: show variables like ‘%storage_engine%’ ;
指定数据库对象的引擎:

create table tb(
    		id int(4) auto_increment ,
    		name varchar(5),
    		dept varchar(5) ,
    		primary key(id)		
    	)ENGINE=MyISAM AUTO_INCREMENT=1
    	 DEFAULT CHARSET=utf8   ;

SQL执行顺序

原因:性能低、执行时间太长、等待时间太长、SQL语句欠佳(连接查询)、索引失效、服务器参数设置不合理(缓冲、线程数)

SQL :

  • 编写过程:select dinstinct …from …join …on …where …group by …having …order by …limit …
  • 解析过程: from … on… join …where …group by …having …select dinstinct …order by limit …

SQL优化, 主要就是在优化索引

  • 索引: 相当于书的目录
  • 索引: index是帮助MySQL高效获取数据的数据结构。索引是数据结构(树:B树(默认)、Hash树…)

索引的弊端:

  1. 索引本身很大, 可以存放在内存/硬盘(通常为 硬盘)
  2. 索引不是所有情况均适用: a.少量数据 b.频繁更新的字段 c.很少使用的字段
  3. 索引会降低增删改的效率(增删改 查)

优势:

  1. 提高查询效率(降低IO使用率)
  2. 降低CPU使用率 (…order by age desc,因为 B树索引本身就是一个好排序的结构,因此在排序时 可以直接使用)

索引创建和删除

分类

  • 主键索引: 不能重复。id 不能是null
  • 唯一索引 :不能重复。id 可以是null
  • 单值索引 : 单列, age ;一个表可以多个单值索引,name。
  • 复合索引 :多个列构成的索引 (相当于 二级目录 : z: zhao) (name,age) (a,b,c,d,…,n)

创建索引
方式一:create 索引类型 索引名 on 表(字段)

  • 单值:create index dept_index on tb(dept);
  • 唯一:create unique index name_index on tb(name) ;
  • 复合索引:create index dept_name_index on tb(dept,name);

方式二:alter table 表名 索引类型 索引名(字段)

  • 单值: alter table tb add index dept_index(dept) ;
  • 唯一: alter table tb add unique index name_index(name);
  • 复合索引 alter table tb add index dept_name_index(dept,name);

注意:如果一个字段是primary key,则改字段默认就是 主键索引

删除索引

  • drop index 索引名 on 表名 ;
    drop index name_index on tb ;

查询索引

  • show index from 表名 ;
  • 或 show index from 表名 \G

explain

分析SQL的执行计划 : explain ,可以模拟SQL优化器执行SQL语句,从而让开发人员 知道自己编写的SQL状况

MySQL查询优化其会干扰我们的优化

优化方法,官网:https://dev.mysql.com/doc/refman/5.5/en/optimization.html

    explain  select  * from tb ;

     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

查询教授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值越大越优先查询 (本质:在嵌套子查询时,先查内层 再查外层)

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 ;

在这里插入图片描述

  • union:上例
  • union result :告知开发人员,那些表之间存在union查询

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不是索引,需要全表所有,即需要所有表中的所有数据

在这里插入图片描述

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,则说明没用索引

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) ;
    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个字节

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

在这里插入图片描述

rows

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

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

在这里插入图片描述

Extra

(1) using filesort : 性能消耗大;需要“额外”的一次排序(查询) 。常见于 order by 语句中。
排序:先查询
10个人 根据年龄排序。

create table test02
(
	a1 char(3),
	a2 char(3),
	a3 char(3),
	index idx_a1(a1),
	index idx_a2(a2),
	index idx_a3(a3)
);

explain select * from test02 where a1 ='' order by a1 ;

在这里插入图片描述
a1:姓名 a2:年龄

explain select * from test02 where a1 ='' order by a2 ; --using filesort

在这里插入图片描述

小结:

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

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

drop index idx_a1 on test02;
drop index idx_a2 on test02;
drop index idx_a3 on test02;

alter table test02 add index idx_a1_a2_a3 (a1,a2,a3) ;
explain select *from test02 where a1='' order by a3 ;  --using filesort
explain select *from test02 where a2='' order by a3 ; --using filesort
explain select *from test02 where a1='' order by a2 ;
explain select *from test02 where a2='' order by a1 ; --using filesort

小结:

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

(2) using temporary: 性能损耗大 ,用到了临时表。一般出现在group by 语句中。

explain select a1 from test02 where a1 in ('1','2','3') group by a1 ;
explain select a1 from test02 where a1 in ('1','2','3') group by a2 ; --using temporary

避免:查询那些列,就根据那些列 group by .

(3) using index :性能提升; 索引覆盖(覆盖索引)。原因:不读取原文件,只从索引文件中获取数据 (不需要回表查询)
只要使用到的列全部都在索引中,就是索引覆盖using index
例如:test02表中有一个复合索引(a1,a2,a3)

explain select a1,a2 from test02 where a1='' or a2= '' ; --using index   	
drop index idx_a1_a2_a3 on test02;
alter table test02 add index idx_a1_a2(a1,a2) ;
explain select a1,a3 from test02 where a1='' or a3= '' ;--using where

如果用到了索引覆盖(using index时),会对 possible_keys和key造成影响:

  • 如果没有where,则索引只出现在key中;
  • 如果有where,则索引出现在key和possible_keys中。

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

explain select a1,a3 from test02 where a3 = '' ; --a3需要回原表查询

(5) impossible where : where子句永远为false

explain select * from test02 where a1='x' and a1='y'  ;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值