10. 索引¶
1. 索引种类¶
B树
R树
hash
全文
2. B树索引类型¶
1.聚簇索引(好处:减少回表,将随机io转换成顺序io)
2.辅助索引(好处:减少排序)
2.1 普通辅助索引
2.2 覆盖索引(好处:减少回表查询几率)
3.唯一键索引
3. 索引作用¶
优化查询
排除缓存,数据库的查询
全表扫描
索引扫描
4.索引管理¶
4.1 创建索引¶
alter table stu add index idx_name(sname);
#方法2(不常用)
create index idx_name on stu(sname);
4.2 删除索引¶
alter table stu drop index idx_name;
#方法2(不常用)
drop index idx_name on stu(sname);
4.3 查看索引¶
desc stu;
show index from stu\G
4.5 联合索引¶
alter talbe city add index idx_co_po(countrycode,population);
4.6 前缀索引¶
alter table city add index idx_dis(district(10));
4.7 唯一索引¶
alter table city add unique index idx_na(name);
5. B树索引结构(原理,未整理)¶
数据页:16kb
# 参考:https://blog.csdn.net/qq_42415326/article/details/90084381?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164575952516780271922868%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164575952516780271922868&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-5-90084381.pc_search_result_cache&utm_term=B%E6%A0%91%E7%B4%A2%E5%BC%95%E5%8E%9F%E7%90%86%E9%80%9A%E4%BF%97%E6%98%93%E6%87%82&spm=1018.2226.3001.4187
6. explain(desc)命令的应用¶
获取优化器选择后的执行计划
6.1 查看执行计划¶
explain select id,name from student where name='oldboy'\G
#重要参数
type: #索引类型
possible_keys: #可能会走的索引
key: #真正走的索引
extra: #额外信息
6.2 索引扫描类型type¶
1.all:全盘扫描
explain select * from city;
线上业务一般不会出现
2.index:索引扫描
explain select countrycode from city;
基本很少出现
3.range:索引范围扫描
explain select * from city where countrycode like 'ch%';
explain select * from city where countrycode in('chn','usa');
><like有额外优化
而in/or没有优化
#注意:%在前走的是all扫描!!!
explain select * from city where countrycode like '%hn';
4.ref:辅助索引等值查询
explain select * from city where countrycode='chn';
union all
select * from city where countrycode='usa';
5.system/const:
#where条件列是主键或唯一键的等值查询时
explain select * from city where id=1;
6.3 extra¶
using temporary
using filesort #####重点
using join buffer
如果出现以上附加信息,检查order by,group by,distinct,join条件列上有没有索引!!!
案例:
explain select * from city where countrycode='chn' order by population;
添加索引后,效率提升
alter table city add index idx_po(population);
explain select * from city where countrycode='chn' order by population;
如果查询条件符合覆盖索引时,优先选择覆盖索引
不符合覆盖索引时,优先走where条件的索引
优化方法:将where列和order列建立联合索引
explain select * from city where countrycode='chn' order by population desc limit 10;
alter table city add index idx_co_po(countrycode,population);
6.4 explain的使用场景¶
1.MySQL出现性能问题
2.获取到问题语句
数据库卡住了
某一段时间慢
可以写入简历
(1)背景:数据库卡住
处理过程:
1.show processlist;获取问题语句
2.explain分析执行计划,有没有走索引,索引的类型
3.建立索引或者更改语句
(2)背景:一段时间慢
处理过程:
1.记录慢日志slowlog,分析slowlog
2.explain法分析SQL执行计划,有没有走索引,索引的类型
3.建索引,改语句
7. 建立索引的原则(运维规范)¶
7.1 建表时必须要有主键,如果没有可以作为主键条件的列,则创建无关列¶
主键索引和唯一键索引,在查询中使用是效率最高的
7.2 经常作为where条件的列,order by,group by,join on的条件列,创建索引¶
1.如果某个字段经常用来作为查询条件,那么该字段的查询速度会影响整个表的查询速度。为这样的字段建立索引,可以提高整个表的查询速度。
1.1 经常查询
1.2 列的重复值少(业务层面调整)
2.经常order,group,join等操作的字段,排序操作会浪费很多时间,如果为其建立索引,可以有效避免排序操作
7.3 最好使用唯一值多的列作为索引,如果索引列重复值较多,可以使用联合索引¶
7.4 列值长度较长的索引列,建议使用前缀索引¶
例如,text、blog类型的字段,进行全文检索会很浪费时间。
如果只检索字段的前面的若干个字符,可以提高检索速度
以上是重点关注的,以下的是能保证则保证的
7.5 降低索引条目,一方面不要创建没用的索引,不常使用的索引要清理¶
索引不是越多越好。
1.每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间越大。
2.修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。
表中的数据呗大量更新,或者数据的使用方式改变后,原有的索引可能不再需要。
数据库管理员应当定期找出这些索引,将他们删除,从而减少索引对更新操作的影响。
7.6 索引维护要避开业务繁忙期¶
大表加索引,要在业务不繁忙期间操作
7.7 开发和DBA经常吵架的原因¶
因为索引维护的问题,索引会造成插入较慢。
解决办法:
插入大量数据时,可以删掉索引
但是一定要记住,当输入完成后,必须再把索引创建好!!!
8. 不走索引的情况(开发规范)¶
8.1 没有查询条件,或者查询条件没有建立索引¶
(1)select * from t1;
在业务数据库中,特别是数据量比较大的表,没有全盘扫描这种需求!
1.对用户查看来讲是非常痛苦的。
2.对服务器来讲是毁灭性的。
(2)select * from t1 where name='z3'; #name列没有索引
解决办法:
1.换成有索引的列作为查询条件
2.将name列建立索引
8.2 查询结果集是原表中的大部分数据(原表的25%以上)¶
当查询的结果集超过总行数的25%,则优化器觉得就没有必要走索引了。
例:t1表id,name,id:1-100w,id列有索引
select * from t1 where id>500000;
解决办法:
1.如果业务允许,可以使用limit控制。
2.结合业务判断,有没有更好的方式,如果没有更好的方案,尽量不要在mysql存放这个数据,可以放到redis里。
id>2 and id<6这种情况可以改写成如下
id=3
union
id=4
union
id=5
8.3 索引本身失效,统计 数据不真实¶
索引有自我维护的能力
对于表内容变化比较频繁的情况,有可能会出现索引失效。
解决办法:
1.重建索引
2.定期检查
8.4 查询条件中使用函数在索引列上,或者对索引列进行运算(+-*/!等)¶
1.算术运算
例:select * from test where id-1=9;
改写:
select * from test where id=10;
2.函数运算
3.子查询
8.5 隐式转换导致索引失效(这点必须重视,开发中经常会犯)¶
例:
create table people(id int not null primary key auto_increment,name varchar(20) not null,telnum char(11) not null unique key);
insert into people(name,telnum) values('zs',110),('l4','119'),('w5',120);
explain select * from people where telnum=110; #全表扫描
explain select * from people where telnum='110'; #const扫描
慢日志会记录下此条语句!
8.6 单独的>,<,in有可能走索引,也有可能不走索引,和结果集有关,尽量结合业务添加limit¶
例:
explain select * from people where telnum <> '110';
explain select * from people where telnum not in ('110','119');
8.7 模糊查询(like"%_")百分号在最前面不走索引¶
例:
explain select * from people where telnum like '11%'; #range索引扫描
explain select * from people where telnum like '%10'; #不走索引
对于%10%类的搜索需求,可以使用elasticsearch数据库
8.8 单独引用联合索引里非第一位置的索引列作为条件查询时,不走索引¶
例:复合索引
create table t1(id int,name varchar(20),age int,sex enum('m','f'),money int);
alter table t1 add index idx_m_a_s(money,age,sex);
走索引的情况:
explain select name,age,sex,money from t1 where money=30 and age=30 and sex='m';
explain select name,age,sex,money from t1 where money=30 and age=30;
explain select name,age,sex,money from t1 where money=30 ande sex='m';
不走索引的情况:
explain select name,age,sex,money from t1 where age=20 and sex='m';
explain select name,age,sex,money from t1 where age=20;
explain select name,age,sex,money from t1 where sex='m';
疑问的情况:
explain select name,age,sex,money from t1 where age=20 and sex='m' and money=30;
explain select name,age,sex,money from t1 where age=20 and money=30;
explain select name,age,sex,money from t1 where sex='m' and money=30;
最后更新:
2022-02-25 03:53:42