【MySql性能优化三】索引优化

时间:2023-01-10 06:07:08
我们在查询表时,如果按照某个字段作为条件或者排序方式时,在这个字段上建立索引,可以加快查询速度。
 那么是不是索引建立的越多,数据库的性能越高呢?这篇博客来研究一下索引的使用。

覆盖索引

什么是覆盖索引呢?
select的数据列只需要从索引列中就可以获得,也就是你查询的结果只需要从你建立的索引列的索引中就可以获取,不需要你额外的读取其他的数据行。
这样就可以使得你的查询被你建的索引所覆盖,索引被称为覆盖索引。

查看 select max(payment_data) from payment 的执行计划

【MySql性能优化三】索引优化

显示rows扫描的行为16086,也就是进行了全表扫描才查询到最后的结果。
如果此时,我们在payment_date字段上面建立一个索引,这时建的就是一个覆盖索引,查看执行计划:

【MySql性能优化三】索引优化

结果显示,扫描的行rows为null,也就是没有扫描就直接可以获得最后的结果。
extra显示:select tables optinized away 不能再优化了。
这就是覆盖索引的效果。

索引的使用

索引在使用时,也需要注意支持它使用的条件。比如下面这种情况的区别.

1、like

在like语句中,mysql数据库对索引的使用也是有区分的。比如: 我们在上面的语句中的title列中建立了索引。
select * from film where title like '%b';

【MySql性能优化三】索引优化

扫描的行为1000行,extra显示的是运用了where查询,并没有运用index,但是,当我们把‘%’换一下位置时,出现的结果是:

【MySql性能优化三】索引优化

扫描的行为63行,extra为使用了索引条件。
索引,在mysql数据库中,如果遇到like语句,要注意‘%’位置的区别。

2、不要在运用索引列时进行行计算

select * from payment where year(payment_date) <2006; 

【MySql性能优化三】索引优化

我们从扫描行发现,他进行了全表扫描,并没有利用我们的索引进行查询。
这是因为我们利用了year这个sql内部的函数,这样会导致在查询时,每一行数据都必须进行计算,这样就会失去索引创建的意义了。
我们可以这样优化,尽量避免计算函数的使用:

【MySql性能优化三】索引优化

我们发现当把year函数去掉后,在查询时,虽然仍然用到了all全表扫描,但是却是基于idx_paydate这个索引的基础上进行的,
并且最后的执行时间有原理的0.09变为了0.00,效果还是很明显的。那么到底应该什么时候使用索引呢?

经过实践我们发现在where,order by(order by语句出现的地方通常会出现filesort,会造成很多的IO),on从句中出现的列使用索引,可以提高效率。
那么,是不是索引越多,性能就越好呢?当然不是,无极必反,索引泛滥也会造成数据库性能下降的。

why索引不是越多越好

首先明白为什么索引会增加速度,DB在执行一条Sql语句的时候,默认的方式是根据搜索条件进行全表扫描,遇到匹配条件的就加入搜索结果集合。
如果我们对某一字段增加索引,查询时就会先去索引列表中一次定位到特定值的行数,大大减少遍历匹配的行数,所以能明显增加查询的速度。
那么在任何时候都应该加索引么?这里有几个反例:1、如果每次都需要取到所有表记录,无论如何都必须进行全表扫描了,那么是否加索引也没有意义了。
2、对非唯一的字段,例如“性别”这种大量重复值的字段,增加索引也没有什么意义。
3、对于记录比较少的表,增加索引不会带来速度的优化反而浪费了存储空间,因为索引是需要存储空间的,而且有个致命缺点是对于
update/insert/delete的每次执行,字段的索引都必须重新计算更新。这样会造成我们的写入效率低下,索引索引并不是越多越好,合适就好!

索引泛滥

重复索引

索引泛滥,在这里主要是不同的用户对数据表中的字段建立索引时,会经常出现建立过索引的字段,又建立了同类型的索引,即索引重复。
比如:对id主键又建立了unique唯一索引。这样做是没有必要的。

冗余索引

冗余索引是指在建立了前缀索引后,又对该列建立了其他的索引。
前缀索引:通常建立在varchar,char,text等数据类型的字段上,比如一个字段是varchar类型的,里面每一个值是几个字母组成的。
那么如果我们建立前缀索引,就是在前几个字母上建立索引,
先让前几个字母进行索引排序,这样在很多情况下也是可以大大的提高查询效率的。

索引维护

那么我们应该如何维护我们的索引呢?通过mysql数据库中的数据统计来查询重复和冗余索引,来对他进行优化。
利用Information_schema数据库的统计信息来查看。
Select a.table_schema as '数据名' ,a.index_name as '索引 1',b.index_name as '索引2',a.column_name as '重复列名' from statistics a join statistics b on a.table_schema=b.table_schema and a.table_name=b.table_name and a.seq_in_index=b.seq_in_index and a.column_name=b.column_name where a.seq_in_index=1 and a.index_name<>b.index_name;

【MySql性能优化三】索引优化

我们发现在sakila数据库中的title列中,建立了两个索引,只是名字不一样而已。这个时候我们就可以根据查询的结果去删除掉一个就可以了。

小结

以上就是mysql数据库中关于索引优化对数据库性能的提高的几种思路。还有很多需要注意的,还是需要实践中慢慢去体会。