文章目录
前言
有时候在MySQL上执行查询时,即使WHERE条件中涉及的字段已经建立了索引,但MySQL仍然没有使用到该索引,下面针对各种可能的原因进行总结。
环境
下文中说到的原因均已在MySQL 5.7.21中进行验证测试。
可能的原因
1)where中的字段涉及隐式数据类型转换
users表的a字段建有索引,数据类型为varchar
SELECT * FROM users WHERE a = 1
上述语句不会使用到a字段的索引,因为a字段的数据类型是varchar,而SQL中的WHERE条件是a=1
,涉及到数字和字符串的隐式转换,应修改为:
SELECT * FROM users WHERE a = '1'
应养成WHERE条件都加单引号的习惯。
2)建有联合索引,但查询条件不符合最左匹配原则
users表的a、b字段建有联合索引(ab)
SELECT * FROM users WHERE b = '1'
上述语句不会使用到ab索引
,不能跳过a字段,只根据b字段来查询。
注意:在MySQL 8.0中新增加了一个叫做 索引跳跃扫描(Index Skip Scan) 的特性,它可以打破最左匹配原则,即使没有用到
a
字段也可以使用联合索引。
3)字段使用了表达式、函数
SELECT * FROM users WHERE b + 1 = 2
SELECT * FROM users WHERE FROM_UNIXTIME(b) = 2
4)模糊查询时,查询条件第一个字符使用了通配符
SELECT * FROM users WHERE b LIKE '%tony'
5)使用了OR查询
SELECT * FROM users WHERE a = 1 OR b = 1
6)优化器使用错了索引
有时候MySQL的优化器会认为有其它的索引更合适,转而使用其它索引来查询的情况,甚至放弃索引使用全表扫描来查询,如果出现这种情况,可以尝试:
- 使用
FORCE INDEX
关键字来强制MySQL使用正确的索引 - 有可能是索引的统计信息不够准确,导致优化器判断出错,使用
ANALYZE TABLE 表名
命令来重新统计索引信息