在数据库查询过程中,通常认为索引是提高数据查询速度的有效方式。然而,在某些情况下,索引可能不仅不会提高效率,反而会降低查询性能。
比较常见的是,当表中的数据量非常小的时候,使用索引可能不会带来性能提升。数据库可能会选择全表扫描而非使用索引,因为在这种情况下,索引的维护成本(如更新、插入或删除数据时维护索引结构)可能超过了它的查询效率优势。
有人疑惑了,为啥优化器这种情况下还会选择索引呢?直接扫全表不就行了么?
确实,这种时候优化器基本就直接扫全表了。但是万一你用了force index,也可能用索引。那么去除force index,让索引失效,也能提升效率。
类似,如果一个索引,他的过滤性不好,数据库优化器可能也会决定全表扫描比使用索引更高效。这是因为如果查询结果包含了表中大部分行,那么使用索引可能需要更多的I/O操作来遍历索引再获取数据,而全表扫描可以更连续地读取磁盘数据。
还有一个就是如果区分度不高也是一样的,就是数据存在严重的不均匀导致倾斜的时候,在这种情况下,优化器可能认为全表扫描比通过索引过滤这些行更有效。
其实以上几条,就是我们在下面这篇文章中讲过的:
还有一种情况也可以通过让索引失效来提升效率。比如说一条查询语句,走A索引和B索引都行,但是优化器选错了,选择了A索引,那么如果我能让他失效,那么他就会选择效率更高的B索引。
很多人会奇怪了,优化器为啥会选错?
这个问题的答案也在上面的那个链接中,你比如说我的这个问题排查过程:
SELECT
*
FROM
`table_name`
WHERE
`DELETED` = 0
AND `STATE` = "INIT"
AND `ID` >= 474968311
AND event_type = ""
ORDER BY
id
LIMIT
100
因为有order by,优化器会倾向于选择ID索引,但是其实STATE的索引过滤性更高好。这个就是一个典型的因为优化器选错了索引导致效率低。那么如果我们能让ID的这个索引失效,那么也能提升效率。
可以用:
SELECT
*
FROM
`table_name`
WHERE
`DELETED` = 0
AND `STATE` = "INIT"
AND `ID` >= 474968311
AND event_type = ""
ORDER BY
id + 0
LIMIT
100
通过这种用函数的方式来让ID索引失效。