Mysql的索引调优详解:如何去创建索引以及避免索引失效
mysql逻辑分层
show variables like "%storage_engine%";
使用哪个引擎在创建表时通过Engine=InnoDB创建,下面正式开始
一、为什么要对sql进行优化:
有时候数据库会出现性能低、执行时间太长、等待时间太长、SQL语句欠佳(连接查询)、索引失效等问题,这些问题会严重拖慢一个系统的速度,因此需要对sql进行优化。
SQL的编写过程和解析过程并非是一致的,下面是两者执行的先后顺序:
编写过程:
select..from..join..on..where..group by...having..order by...limit.
解析过程:
from..on..join..where..group by....having...select..order by...limit..
二、SQL如何优化:
索引:相当于书的目录,是帮助MYSQL高效获取数据的数据结构。就好比我们查字典,如果没有目录查一个字就需要遍历整本字典,而有了目录之后只需要按目录查询。索引的数据结构有(树:B+树(默认)、Hash树等等)
B+树是一种数据结构,所有的元素全部放在叶子节点,因此B+树查询数据都需要n次,n与树的高度相同
2.1、索引的弊端:
2.2 索引的优势:
2.3 关于索引的分类:
单值索引:单列的索引,比如学生表中的grade。一个表可以有多个单值索引
复合索引:多个列构成的索引,(name,grade)构成索引后先查name,再查grade
2.4 如何创建索引:
单值索引:
create index name_index on student(name);
唯一索引:
create unique index id_index on student(id);
复合索引:
create index name_grade_index on student(name,grade);
alter table 表名 add 索引类型 索引名(字段);
单值索引:
alter table student add index name_index(name);
唯一索引:
alter table student add unique index id_index(id);
复合索引:
alter table student add index name_grade_index(name,grade);
删除索引:
drop index 索引名 on 表名
2.5 explain关键字
通过explain关键字可以看到sql语句的执行过程,其中type、key、key_len、Extra需要尤其注重
id:标识符
如果有多个id,id值相同,顺序执行;id值不同,id值越大越优先查询
union:当查询时用到了table1 union table2,table1类型是derived,table2的类型是union
system>const>eq_ref>ref>range>index>all
system>const存在于理想状态,实际能达到ref,索引的优化一般到ref为止
const:仅仅能查到一条数据的SQL,用于主键索引和唯一索引
eq_ref:唯一性索引:对于每个索引键的查询,返回匹配唯一行数据(有且只有1个,不能多、不能0)
ref:非唯一性索引,对于每个索引键的查询,返回匹配的所有行
range:检索指定范围的行,where后面是一个范围查询(between,>,<)等。
rows:被索引优化查询的数据个数(实际通过索引查询到的数据个数)
using filesort:性能消耗大;需要“额外”的一次排序,常见于orderby语句
using temporary:性能损耗大,用到了临时表,一般出现在groupby中
using index:性能提升;索引覆盖(覆盖索引)。原因:不读取原文件,只从索引文件中获取数据
三、索引优化实例:
create table book
(
bid int(4) primary key,
name varchar(20) not null,
authorid int(4) not null,
typeid int(4) not null
);
insert into book values(1,'java',1,1);
insert into book values(2,'c',2,2);
insert into book values(3,'math',3,3);
insert into book values(4,'english',4,3);
首先不建立索引查看查询情况:虽然我没建立索引,但是mysql5.7自动建立了主键索引,现在的type是index,继续优化:
alter table book index a_t_b(authorid,typeid,bid);
此时的type已经到了ref,达到了最好的优化效果,在额外信息中依旧存在using where,因为当使用in时,部分索引可能会失效,所以一部分数据从索引中查询,一部分数据回表查询。
四、加索引的技巧:
select ... from .... where 小表.x=大表.x;
如果主查询的数据集大,则使用in,如果子查询的数据集大,则使用exist
select .. from table where exist/in (子查询)
五、避免索引失效的原则
1、复合索引不要跨列或无序使用(最佳左前缀):索引的顺序和sql语句查询时的顺序一致
name的属性是varchar,这里变成了int
select * from teacher where name=123
六、慢查询日志的使用
慢查询日志是mysql提供的一种日志记录,用于记录Mysql响应时间超过阈值的Sql语句(long_query_time,默认10秒)。
查看慢查询日志
show variables like '%slow_query_log%';
临时开启慢查询日志
set global slow_query_log=1;
slow_query_log=1
slow_query_log_file=XXX/slow.log
show variables like '%long_query_time%';
更改慢查询时间阈值
show variables like '%long_query_time%';
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了