一次奇怪的 MySQL 索引失效问题

今天碰到一个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强制使用某个索引。

其他引起失效原因

经验分享 程序员 微信小程序 职场和发展