在上文中,我们介绍了MySQL中的两种主要的索引–B-Tree索引和Hash索引。虽然使用索引会带来很大程度上的性能优化。但是,索引的不当使用同时也会引起性能的急剧下降。今天我们就来聊聊索引的优化问题。
首先讨论两个问题:
问题
1、为什么要使用索引?
谈到为什么要使用索引,大家第一时间想到的就是提升查询效率吧。那除了这个用途之外索引还有其他的用途吗?下面我们就来聊一聊:
1)、使用索引大大减少了存储引擎需要扫描的数据量。例如:在InnoDB存储引擎中,默认索引的一页为16k,可以存放更多的数据。
2)、索引可以帮助我们进行排序以避免使用临时表。例如:B-Tree索引用于排序,减少临时表的IO消耗,提高MySQL的处理能力。
3)、因为数据库中数据的物理地址一般是随机存放,而索引是顺序存储的,所以索引可以把随机I/O变为顺序I/O。
2、索引是不是越多越好?
答案肯定不是。因为索引同时也会带来性能损耗,主要有以下两个方面:
1)、索引会增加写操作的成本
数据的更新必须维护索引和统计信息。索引越多,修改数据的时间越长。所以引入了插入缓存来减少这种写操作的成本。
这里需要说明的一点是,引入插入缓存并不能增加数据的导入速率。相反提高导入速率的最好方法就是删除索引索引。但应该保留自增的主键ID,否则,导入速率可能更低。
2)、太多的索引会增加查询优化器的选择时间
之前也说过,MySQL查询优化器会为查询选择合适的索引。若是同一个语句有很多索引可以使用,也会增加查询优化器对索引的选择时间。
在解决了上述两个问题之后,我们接下来就具体谈一谈索引的一些优化策略。
索引的优化策略
索引列上不能使用表达式或函数
如果查询中的列不是独立的,则MySQL是不会使用索引的。比如下面这个示例:
select ID from product where to_days(out_date) - to_days(cur_date) <= 30;
在这条语句中若out_data是索引列,to_days()是函数,则这个查询无法使用out_date列的索引。所以,我们因该养成简化where条件的习惯,始终将索引列单独放在比较符号的一侧。对上条查询语句的优化如下:
select out_date <= data_add(cur_da