MYSQL使用索引的查询有两个步骤:读取索引数据获取主键ID
根据主键ID从表中获取数据。
如果第1步,在一个很大的表中查到少量的数据,那么在第2步就会只需要很少的时间。
对于“=”这个比较,第一步读取索引数据效率是O(log N),速度很快。
(不了解为什么“=”是O(log N)的话请复习数据结构树那一部分)
第一步和第二部都很快,所以走索引效率很好。
如果是“!=”,第一步中读取索引数据的效率就不是O(log N)了,需要全部读取索引的数据。 效率O(N).
一般情况,“!=”操作会选择表中绝大部分数据(假设一个字段有10个可选值,平均分布,不等操作就会选出其中90%的数据),第2步操作时间和全表扫描时间差不多(看数据量来说9:10)。然而还需要加上第一步读取索引的时间。这样一来,所花的总时间就比不走索引还多。
对于这种情况,数据库当然选择不走索引了。
不过,不等于不能使用索引这个说法是不准确的。
select col1,count(*) from table where col1!='xxxx' 就可以走col1的索引。
select col1, col2 from table where col1!='xxxx' 可以走col1,col2上的复合索引
什么情况下,"!=" 和 "not in"可以走索引?
直接读取索引,不用读取表里的数据,就可以获取所需数据的SQL,"!="和"not in"也可以走索引
换个说法是,满足Covering Index使用条件的SQL,"!="和"not in"也可以走索引