MySQL高级学习(7)索引优化

本文详细介绍了MySQL索引优化的要点,包括最左前缀法则、避免操作索引列、使用覆盖索引、处理不等于和LIKE操作符的场景、NULL值的影响、以及LIKE通配符的使用。同时,提出了优化建议,如选择过滤性好的索引和避免OR操作等,并通过实例分析了索引在不同查询中的应用情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mysql 索引优化

1. 最左前缀:如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始并且不跳过索引中的列。

 and 忽略左右关系。既即使没有按顺序 由于优化器的存在,会自动优化。经过试验结论  建立了 idx_nameAge 索引  id 为主键

    (1).当使用覆盖索引的方式时,(select name/age/id from staffs where age=10 (后面没有其他没有索引的字段条件)),即使不是以 name 开头,也会使用 idx_nameAge 索引。

    既 select 后的字段 有索引,where 后的字段也有索引,则无关执行顺序。

    (2)除开上述条件 才满足最左前缀法则。

        EXPLAIN SELECT * FROM staffs WHERE age = 25 AND pos = 'dev';

        EXPLAIN SELECT * FROM staffs WHERE pos = 'dev';

2.不在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描

3.存储引擎不能使用索引中范围条件右边的列

      where条件查找范围条件,type回事range 并且后面的where条件 索引失效

4.尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *

       会用到index extra中 会using index 性能更好

5.mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描

     索引  idx_nameAgeJob

             idx_name

      使用 != 和 <> 的字段索引失效( != 针对数值类型。 <> 针对字符类型

          前提 where and 后的字段在混合索引中的位置比当前字段靠后  where age != 10 and name='xxx'  ,这种情况下,mysql自动优化,将 name='xxx' 放在 age !=10 之前,name 依然能使用索引。只是 age 的索引失效)

6.is not null 也无法使用索引,但是is null是可以使用索引的

7.like以通配符开头('%abc...')mysql索引失效会变成全表扫描的操作

        like ‘%abc%’ 或者 "%abc" type 类型会变成 all

         like ‘abc%’ type 类型为 range ,算是范围,可以使用索引

问题:解决like '%字符串%'时索引不被使用的方法??

     利用覆盖索引去解决

       select name,age,email from tables ... type会是index using index

       select id from tables type也是index using index id是主键索引 也可以使用到

8.字符串不加单引号索引失效

       2000和‘2000’是不一样的,字符串类型的不可以不加单引号,mysql会底层进行转换导致索引失 效,使用了函数造成索引失效

9.少用or,用它来连接时会索引失效

总结

顺口溜

带头大哥不能死(复合索引的最左前缀原则,最左边的索引不能没有,没有会导致索引失效)

中间兄弟不能断(复合索引中间的索引不能没有,否则索引只会生效第一个,后面的索引失效)

索引列上不计算(计算、函数、(自动or手动)类型转换)

like百分加右边

范围后面全失效(范围查询后面的索引会失效)

字符串里有引号(mysql会底层进行转换导致索引失效)

 假设index(a,b,c) 复合索引Where语句索引是否被使用

1.where a = 3     使用到a

2.where a = 3 and b = 5      使用到a,b

3.where a = 3 and b = 5 and c = 4    使用到a,b,c

4.where b = 3 或者 where b = 3 and c = 4  或者 where c = 4 没用到

5.where a = 3 and c = 5   使用到a, 但是c不可以,b中间断了

6.where a = 3 and b > 4 and c = 5      使用到a和b, c不能用在范围之后,b后断了

7.where a = 3 and b like 'kk%' and c = 4    使用到a,b, c 但是type为range

8.where a = 3 and b like '%kk' and c = 4     只用到a

9.where a = 3 and b like '%kk%' and c = 4     只用到a

10.where a = 3 and b like 'k%kk%' and c = 4   使用到a,b,c 但是type为range 同7

面试题举例

【建表语句】

create table test03(

 id int primary key not null auto_increment,

 c1 char(10),

 c2 char(10),

 c3 char(10),

 c4 char(10),

 c5 char(10)

);

insert into test03(c1,c2,c3,c4,c5) values('a1','a2','a3','a4','a5');

insert into test03(c1,c2,c3,c4,c5) values('b1','b2','b3','b4','b5');

insert into test03(c1,c2,c3,c4,c5) values('c1','c2','c3','c4','c5');

insert into test03(c1,c2,c3,c4,c5) values('d1','d2','d3','d4','d5');

insert into test03(c1,c2,c3,c4,c5) values('e1','e2','e3','e4','e5');

【建索引】

create index idx_test03_c1234 on test03(c1,c2,c3,c4);

问题:我们创建了复合索引idx_test03_c1234 ,根据以下SQL分析下索引使用情况?

explain select * from test03 where c1='a1'; 用到了c1

explain select * from test03 where c1='a1' and c2='a2'; 用到了c1 c2

explain select * from test03 where c1='a1' and c2='a2' and c3='a3';用到了c1 c2 c3

explain select * from test03 where c1='a1' and c2='a2' and c3='a3' and c4='a4';用到了c1 c2 c3 c4

1)explain select * from test03 where c1='a1' and c2='a2' and c3='a3' and c4='a4'; 

用到了c1 c2 c3 c4 mysql优化器自动优化where后面的and顺序

2) explain select * from test03 where c1='a1' and c2='a2' and c4='a4' and c3='a3'; 

用到了c1 c2 c3 c4 mysql优化器自动优化where后面的and顺序

3) explain select * from test03 where c1='a1' and c2='a2' and c3>'a3' and c4='a4';

用到了c1 c2 c3用到了排序 c4没用到

4) explain select * from test03 where c1='a1' and c2='a2' and c4>'a4' and c3='a3';

用到了c1 c2 c3 c4用来排序

5) explain select * from test03 where c1='a1' and c2='a2' and c4='a4' order by c3;

 用到了c1 c2 c3作用在排序而不是查找 c4没用到

6) explain select * from test03 where c1='a1' and c2='a2' order by c3;

用到了c1 c2 c3作用在排序而不是查找

7) explain select * from test03 where c1='a1' and c2='a2' order by c4; 

用到了c1 c2 c4在排序 出现了using filesort 需要优化

8) 

8.1explain select * from test03 where c1='a1' and c5='a5' order by c2,c3; 

 只用c1一个字段索引,但是c2、c3用于排序,无filesort

8.2explain select * from test03 where c1='a1' and c5='a5' order by c3,c2;

 出现了filesort,我们建的索引是1234,它没有按照顺序来,3 2 颠倒了

9) explain select * from test03 where c1='a1' and c2='a2' order by c2,c3;

用到了c1 c2 索引 c2 c3 用来排序

10)explain select * from test03 where c1='a1' and c2='a2' and c5='a5' order by c2,c3;       

 同上用c1、c2两个字段索引,但是c2、c3用于排序,无filesort

 explain select * from test03 where c1='a1' and c2='a2' and c5='a5' order by c3,c2;             

 本例有常量c2的情况,和8.2对比 因为where条件有了c2的查询 所以c2已经变成了常量,在order by的时候 c2也就成了常量, 也就只有c3进行了order by 所以没有了filesort

 explain select * from test03 where c1='a1' and c5='a5' order by c3,c2;       

使用到了c1索引 出现了filesort排序,需要优化                        

11)explain select * from test03 where c1='a1' and c4='a4' group by c2,c3;

使用到了一个c1 分组之前必排序,c2 c3 进行了排序 分组

12)explain select * from test03 where c1='a1' and c4='a4' group by c3,c2;

使用到了一个c1 分组之前必排序,出现了 Using where; Using temporary; Using filesort 

 

一般性建议

1.对于单键索引,尽量选择针对当前query过滤性更好的索引

2.在选择组合索引的时候,当前Query中过滤性最好的字段在索引字段顺序中,位置越靠前越好。(避免索引过滤性好的索引失效)

3.在选择组合索引的时候,尽量选择可以能够包含当前query中的where字句中更多字段的索引

4.尽可能通过分析统计信息和调整query的写法来达到选择合适索引的目的

 

sql优化步骤

1.观察,至少跑一天,然后看看生产的慢sql的情况

2.开启慢查询日志,超过设定慢查询时间的,抓取出来

3.explain+慢sql分析 (会解决80%)

4.show profile 查询sql在mysql服务器中的执行细节和生命周期情况

5.运维 or DBA 进行sql数据库的数据库服务器参数调优

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值