mysql 索引 失效 mysql索引失效的场景_mysql


文章目录

  • 测试表
  • 测试数据
  • 🍊查询条件包含or,可能导致索引失效
  • 分析&结论
  • 🍊如何字段类型是字符串,where时一定用引号括起来,否则索引失效
  • 🍊like通配符可能导致索引失效
  • 🍊联合索引,查询时的条件列不是联合索引中的第一个列,索引失效
  • 🍊mysql估计使用全表扫描要比使用索引快,则不使用索引
  • 🍊mysql使用in查询时



工作常用,面试必问类型,在这里总结下😂;

测试表

DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`  (
  `id` int(0) NOT NULL,
  `u_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `u_age` int(0) NULL DEFAULT NULL,
  `u_birth` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `age`(`u_age`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

测试数据

mysql 索引 失效 mysql索引失效的场景_mysql 索引 失效_02

🍊查询条件包含or,可能导致索引失效

  • 首先根据索引u_age进行查询,发现使用了索引:
EXPLAIN SELECT
	* 
FROM
	sys_user 
WHERE
	u_age = 10

mysql 索引 失效 mysql索引失效的场景_字段_03

  • 加上or之后
EXPLAIN SELECT
	* 
FROM
	sys_user 
WHERE
	u_age = 10 or u_birth = 1000

mysql 索引 失效 mysql索引失效的场景_面试_04

分析&结论

  • 加or之后,第一次查询使用u_age索引,第二次因为u_birth没有索引,还是需要全表扫一次,索性就直接全表扫描了,一遍就完事;
  • mysql是有优化器的,处于效率与成本考虑,遇到or条件,会让索引失效;
  • 如果把u_birth也加上索引的话,就会走索引

🍊如何字段类型是字符串,where时一定用引号括起来,否则索引失效

  • 因为如果不加引号的话,类型不匹配;
🍊like通配符可能导致索引失效
  • 并不是用了like通配符,索引一定失效,而是like查询是以%开头,才会导致索引失效;
  • 但也不绝对,如果使用覆盖索引去查询的话,就算两边都加了%号,同样也是会走索引;
🍊联合索引,查询时的条件列不是联合索引中的第一个列,索引失效
  • 理解这个要懂得索引底层叶子节点的结构,在这里写的话篇幅太大了,我单独开了篇文章;

以下为基本常识,就不一一举例子了

  1. 在索引列上使用mysql的内置函数,索引失效
  2. 对索引列运算(如,+、-、*、/),索引失效
  3. 索引字段上使用(!= 或者 < >,not in)时,可能会导致索引失效
  4. 索引字段上使用is null, is not null,可能导致索引失效
  5. 左连接查询或者右连接查询查询关联的字段编码格式不一样,可能导致索引失效
🍊mysql估计使用全表扫描要比使用索引快,则不使用索引
  • 这个主要看MySQL优化器如何判断
🍊mysql使用in查询时
  • 在低版本中(mysql-5.5.40),如果in查询的数量比较多,会全表扫描,in的数量比较少的话,会走索引;(3个以下)
  • 在mysql-8版本,使用in查询也是会走索引的(range),这里做了优化;