select x from table where a = 1 这条sql导致索引失效的原因有哪些?¶
典型回答¶
这是一个典型的索引失效的场景题,那么分析下都有可能是哪些原因。
1、发生了隐式类型转换
索引的字段,如果类型不一致,比如a本来是个字符串类型,但是按照int类型查询,这时候就会出现隐式类型转换,那么也会导致索引失效。
2、数据出现严重倾斜
这是最典型也最重要的情况。假设在 1000 万行数据的表中,有 999 万行的 a 都等于 1,只有 1 万行是其他值。那么当你查询 a = 1 时,使用索引查询需要访问 999 万个索引条目,然后再回表 999 万次,这个成本远高于直接全表扫描(一次顺序 I/O 读完所有数据)。这种情况下也可能不会走索引
3、a这个字段区分度不高
这个和上面的情况有点像,就是如果a这个字段的值只有很少的可能,比如像性别这种,只有男或者女,他也可能会导致索引失效。
但是其实问题本质还是因为1这个值的数据量太大了,而如果1比较少,比如像我在下面给大家讲的情况,也是可以用到索引,并且效果也会很好的。
4、表中数据量过小
走不走索引是优化器决定的,而优化器会根据执行的成本来预估要不要走索引,有一种特殊情况,那就是当表中数据量很少,比如只有几十条甚至几百条数据时,查询优化器回去认为通过索引去查找再回表(如果索引不是覆盖索引)的成本,可能高于直接进行全表扫描的成本。因为全表扫描可以将数据一次性加载到内存中,而索引查找涉及随机的 I/O 操作。
5、索引不正确
题目中只给了SQL的情况,但是并没有说索引是怎么建的,如果a这个字段没有索引,或者说是他只是个联合索引并且不在最左边,比如联合索引(b,a),那么因为不遵循最左前缀匹配,也会导致索引失效
6、统计信息不准
InnoDB存储引擎依赖统计信息来决定使用哪个索引,如基数性、选择性这些都是统计信息。如果这些统计信息过时或不准确,优化器可能做出错误的决策。
一般在频繁的插入和删除后,还没来得及更新统计信息的情况下,也可能会出现这种情况。这时候也会导致索引失效。