索引是数据库设计中特殊的数据存储结构,它能使我们的查询效率加倍,合理的使用索引让我们的性能得到质的提升,但是开发过程中,难免各种各样的业务需求可能会导致我们不意间写的SQL语句索引失效,这里整理了一些让索引失效的SQL操作有哪些。 下面是User表结构,主键只有一个id,数据量一共是800w条,根据不同测试条件后续会修改索引。
CREATE TABLE `csdn`.`无标题` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`mobile` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`open_id` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`region_id` int(10) NULL DEFAULT NULL,
`addr` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`sex` tinyint(2) NOT NULL DEFAULT 0 COMMENT '0女1男',
`state` tinyint(2) NOT NULL DEFAULT 1 COMMENT '0冻结1正常',
`created_date` datetime(0) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `name`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8003859 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
1.Like语句可能会导致失效(注:可能)
前置条件说明 主键:id (B+tree)、name(B+tree)



覆盖索引的缘故,当我们加了索引的列查询的时候刚好也只查询这个列,就不需要回表操作所以这个情况是会走索引的。别急,还有一种情况:

2.or关键字可能会导致失效(注:可能)
前置条件说明 主键:id (B+tree)、name(B+tree)


3.索引列进行函数或者运算符操作可能导致失效(注:可能)
前置条件说明 主键:id (B+tree)、name(B+tree)


覆盖索引试试:

4.索引列使用!= <> 可能会导致失效(注:可能)
前置条件说明 主键:id (B+tree)、name(B+tree)

覆盖索引呢,试试:

覆盖索引的情况下还是会走索引的。别急,我们看看这一个情况:

5.索引列使用is not null可能导致失效(注:可能)
前置条件说明 主键:id (B+tree)、name(B+tree)


6.索引是字符串类型的列查询不带引号可能会导致失效(注:可能)
前置条件说明 主键:id (B+tree)、name(B+tree)


覆盖索引其实还是会走索引的
7.联合索引不遵循最左匹配原则会导致索引失效
前置条件说明 主键:id (B+tree)、name(B+tree)、(region_id,sex)(B+tree)




最左匹配原则,也就是说这个(region_id,sex)的联合索引其实可以解释为两个索引的组合:region_id,(region_id,sex),所以如果不满足最左匹配原则就会索引失效。(A,B,C)类型的符合索引,where条件后面如果是A,AB,ABC都可以命中索引。
8.试用not in可能导致失效(注:可能)
前置条件说明 主键:id (B+tree)、name(B+tree)



9.外联查询字符集不同意可能导致失效或索引利用率降低
前置条件说明 主键:id (B+tree)、name(B+tree)、mobile(B+tree)


10.优化器认为全表扫描比使用索引更有效率是会失效
这类情况几乎是不大可能发生,但是从逻辑上讲是存在的。当一个列的值存在大量重复时,比如性别,各种状态,当一部分值的数据量几乎碾压性的大于另一个值,优化器认为扫描索引和回表所带来的消耗和全表扫描相差不大时可能出现,但是此类情况和数据库的设计一般不会出现。