今天碰到一个MySQL索引失效的问题,想当年面试,面试官问我有没有遇到过索引失效的场景时,我羞涩的答了一个“没有”,甚是尴尬。如今也遇到了MySQL优化器判断失误的时候,特此记录下来,以备下次面试时吊打面试官。
记录问题
tb_order 表有索引

搜索时条件也没有违反索引规则,显示可以使用索引,但却没有实际使用。

强制使用 idx_contract_time 索引,发现是可以提高查询速度的。

或者将pay_amount字段加进索引中,也可以走索引


查询资料
即使存在辅助索引idx_contract_time, 优化器最后可能还是选择primary聚集索引。
原因是:用户选取的数据是需要整行信息,而idx_contract_time索引不能覆盖到我们要查询的信息,因此在对idx_contract_time索引查询到指定数据后,还要再进行一次回表访问来查找整行的信息。
虽然idx_contract_time索引中数据是顺序存放的,但是再进行一次书签查找的数据则是无序的,变成了磁盘上的离散读操作。如果访问的数据量很小,那优化器还是会选择辅助索引,但访问的数据占整个表蛮大一部分时(一般20%),优化器会选择通过聚集索引来查找数据,因为顺序读的操作会远大于离散读。
如果不能使用覆盖索引的情况,优化器只有数据量小的时候才会使用辅助索引。这是由传统的机械硬盘特性决定的。若使用固态硬盘,随机读操作很快,且有足够的自信能确认使用辅助索引可以带来更好的性能,可以使用Force index强制使用某个索引。
mysql在扫描情况下会选择全表扫描而不是走索引、mysql优化器选择使用或者不用索引
其他引起失效原因
后端程序员必备:索引失效的十大杂症