索引优化实例

236 阅读3分钟

1、全值匹配

2、最左前缀法则

如果索引了多列,查询从索引的最左前列开始并且不调做索引中的列

3、不在索引列上做任何操作

会导致索引失效
select * from table where date(create_time) = '2022-02-25'不走索引
优化为:
select * from table where create_time >= '2022-02-25 00:00:00' and create_time <= '2022-02-25 23:59:59'

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

语句1:select * from table where name = 'aa' and age = 20 and city = 'beijing'
语句2:select * from table where name = 'aa' and age > 20 and city = 'beijing'
语句2只会走name和age索引

5、尽量使用覆盖索引(只访问索引的查询),减少*

6、在使用!=或者<>时,无法使用索引

7、is null,is not null一般也无法用索引

8、like 以通配符开头,索引会失效

语句1:select * from table where name like '%aa'不走索引,因为%在前面,相当于aa之前可能会是dufdaaa,把*替换成覆盖索引可以相对优化
语句2:select * from table where name like 'aa%'走索引,因为可以确定前面是aa

9、字符串不加单引号,索引失效

10、少用or或in,不一定会使用索引

11、范围查询优化

select * from table where age > 0 and age < 4000不走
优化:大范围拆成小范围:
select * from table where age > 0 and age <= 1000 select * from table where age > 1000 and age <= 2000 select * from table where age > 2000 and age <= 3000 select * from table where age > 3000 and age <= 4000

索引下推

在辅助联合索引情况下,语句select * from table where name like 'aa%' and age > 20 and city = 'beijing',5.6版本之前,是只根据name找出主键索引id后回表查询的,在5.6之后,会继续下推,使用到age和city的条件找出主键索引id,减少了回表查询的id数量。
索引下推只能使用在innodb下的二级索引,因为主键索引子节点上保存的是全行数据。

order by优化 name,age,city

1、select * from table where name = 'a' and city='beijing' order by age;extra会走索引,因为name确定,age有序
2、select * from table where name = 'a' order by city;extra不会走索引,因为name确定,age不确定,city不有序
3、select * from table where name = 'a' order by age,city;extra会走索引,因为name确定,age,city有序
4、select * from table where name = 'a' order by city,age;extra不会走索引,因为name确定,age,city排序位置反了
5、select * from table where name = 'a' and age = 20 order by city,age;extra会走索引,因为name确定,age确定,city有序,排序正常
6、select * from table where name = 'a' order by age asc,city desc;extra不会走索引,因为city desc,与索引的排序方式不同
7、select * from table where name in ('a','b') order by age,city;extra不会走索引,对于排序,多个条件也是范围查询
8、 select * from table where name > 'a' order by name;extra不会走索引,因为数据量过大。可以覆盖优化:select name,age,city from table where name > 'a' order by name

group by和order by类似,本质上是先排序后分组,遵循索引创建顺序的最左前缀法则。如果gropu by不需要排序,可以用order by null。尽量在where中写条件,避免having。

另外

1、like aa% 相当于 = aa,%aa和%aa%相当于范围
2、where name like 'a%aa%' 相当于 name = 'a',会走索引
3、force index可以强制走索引
4、在某些情况下,mysql会根据实际情况,自动选择是否走索引,因为在一些特殊情况下(数据结构,数据量),并不一定走索引就一定快。 例如第10条。 5、explain分析时,并不是rows越小查找时间越短,最终还是看语句的执行时间
6、使用set session optimizer_trace="enabled=on",end_markers_in_json=on来打开mysql的trace工具,在执行完sql语句之后,继续使用select * from information_schema.OPTIMIZER_TRACE;mysql会显示出sql语句运行的过程。

总结

查找语句尽可能的使得索引有序排列,增加使用到索引的可能性