背景
最近生产爆出一条慢sql,原因是用了or和!=,导致索引失效。于是,总结了索来@源gao*daima.com搞@代#码网引失效的十大杂症,希望对大家有帮助,加油。
一、查询条件包含or,可能导致索引失效
新建一个user表,它有一个普通索引userId,结构如下:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL, `age` int(11) NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), KEY `idx_userId` (`userId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
执行一条查询sql,它是会走索引的,如下图所示:
把or条件+没有索引的age加上,并不会走索引,如图:
分析&结论:
- 对于or+没有索引的age这种情况,假设它走了userId的索引,但是走到age查询条件时,它还得全表扫描,也就是需要三步过程: 全表扫描+索引扫描+合并
- 如果它一开始就走全表扫描,直接一遍扫描就完事。
- mysql是有优化器的,处于效率与成本,遇到or条件,索引可能失效,看起来也合情合理。
注意: 如果or条件的列都加了索引,索引可能会走的,大家可以自己试一试。
二、如何字段类型是字符串,where时一定用引号括起来,否则索引失效
假设demo表结构如下:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` varchar(32) NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), KEY `idx_userId` (`userId`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
userId为字符串类型,是B+树的普通索引,如果查询条件传了一个数字过去,它是不走索引的,如图所示:
如果给数字加上”,也就是传一个字符串呢,当然是走索引,如下图: