跳转至

select x from table where a = 1 这条sql导致索引失效的原因有哪些?

典型回答

这是一个典型的索引失效的场景题,那么分析下都有可能是哪些原因。

21_✅索引失效的问题是如何排查的,有哪些种情况?

1、发生了隐式类型转换


索引的字段,如果类型不一致,比如a本来是个字符串类型,但是按照int类型查询,这时候就会出现隐式类型转换,那么也会导致索引失效。

2、数据出现严重倾斜


这是最典型也最重要的情况。假设在 1000 万行数据的表中,有 999 万行的 a 都等于 1,只有 1 万行是其他值。那么当你查询 a = 1 时,使用索引查询需要访问 999 万个索引条目,然后再回表 999 万次,这个成本远高于直接全表扫描(一次顺序 I/O 读完所有数据)。这种情况下也可能不会走索引

3、a这个字段区分度不高

这个和上面的情况有点像,就是如果a这个字段的值只有很少的可能,比如像性别这种,只有男或者女,他也可能会导致索引失效。

但是其实问题本质还是因为1这个值的数据量太大了,而如果1比较少,比如像我在下面给大家讲的情况,也是可以用到索引,并且效果也会很好的。

50_✅区分度不高的字段建索引一定没用吗?


4、表中数据量过小

走不走索引是优化器决定的,而优化器会根据执行的成本来预估要不要走索引,有一种特殊情况,那就是当表中数据量很少,比如只有几十条甚至几百条数据时,查询优化器回去认为通过索引去查找再回表(如果索引不是覆盖索引)的成本,可能高于直接进行全表扫描的成本。因为全表扫描可以将数据一次性加载到内存中,而索引查找涉及随机的 I/O 操作。

5、索引不正确


题目中只给了SQL的情况,但是并没有说索引是怎么建的,如果a这个字段没有索引,或者说是他只是个联合索引并且不在最左边,比如联合索引(b,a),那么因为不遵循最左前缀匹配,也会导致索引失效


63_✅什么是最左前缀匹配?为什么要遵守?

6、统计信息不准

InnoDB存储引擎依赖统计信息来决定使用哪个索引,如基数性、选择性这些都是统计信息。如果这些统计信息过时或不准确,优化器可能做出错误的决策。

一般在频繁的插入和删除后,还没来得及更新统计信息的情况下,也可能会出现这种情况。这时候也会导致索引失效。


82_✅为什么MySQL会选错索引,如何解决?