in后使用普通索引字段到底是否会使用索引(2021-4-14)

1.建表语句以及数据

CREATE TABLE `mashibing`.`Untitled`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `id_status`(`status`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 66 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

除了主键索引外,还加了status字段的普通索引
表中先插入了14条记录(重要,此时数据量仅为14条!!!)
在这里插入图片描述

2.SQL语句及执行

1.  explain SELECT id,status,name FROM user where status in ('M','F');
2.  explain SELECT id,status,name FROM user where status in ('M','L','F');



3.   explain SELECT id,status FROM user where status in ('M','F');
4.   explain SELECT id,status FROM user where status in ('M','L','F');


5.  explain select id,name,status  from user where id in (1,4);
6.  explain select id,name,status  from user where id in (1,4,9);

explain结果
1,2条执行结果
在这里插入图片描述
3,4条执行结果
在这里插入图片描述

5,6条执行结果
在这里插入图片描述
对比结果
1. 第 1,2条语句没有使用索引,而下方第3,4条语句都使用了索引,焦点在于有没有select name字段,只要select name字段就无法使用status上的索引
2. 第5,6条语句使用主索引,未使用status的普通索引,仍旧可以使用in,会用到主键索引

此时我以为是in后使用普通索引无法使用索引检索,只能使用主键索引,百度了一下发现可能还与数据量有关,于是增加数据量再执行,加到65条数据


此时执行sql语句,3456条语句执行结果不变,看第1,2条
第1条
第2条

可以看到此时第1条使用了索引,但第2条仍旧未使用索引。
其可能是因为优化器在不同数据量下的优化选择方案:
数据量较小时,全表扫描(ALL)的成本低于普通索引范围查询(range),数据量较大时才会使用普通索引范围查询,
但如果是主键字段不管数据量大小都会使用主键索引范围查询;

3.验证

可以使用 show status like ‘last_query_cost’; 语句查看查询计划的成本,对比一下即可验证
设计对照:建立一个表user2,字段和user一样,但不给status建立普通索引,以 explain SELECT id,status,name FROM user where status in (‘M’,‘F’) 为测试语句;

14条数据时没有普通索引检索和有普通索引查询成本:

14 没有
15 有
65条数据时没有普通索引检索和有普通索引查询成本:
65 没有
65 有

数据量是否使用索引查询成本
14 条3.799
14条3.799
65条13.999(修改)
65条13.209

4.结论:

数据量小的时候,都不走索引,所以查询成本相同(不知道在这种情况下如何让数据库强行使用成本高的方案,所以没法测出小数据量时走索引的查询成本)
当数据量增大的时候,走索引的成本为13.209,不走索引的成本为13.999,所以此时走索引,所以in后普通索引到底会不会使用取决于数据量大小以及数据库的优化方案(如果哪位大佬知道其详细的成本计算方法,望告知一下)。

P.S.

更新

1. 查询后可以使用 explain SELECT id,status,name FROM user force index(idx_status) where status in (‘M’,‘F’); 该语句强行指定索引(从该博客得知,点击跳转

在这里插入图片描述
在这里插入图片描述
此时使用了索引,但少数据量时强行使用索引的成本13.209>>3.799,因为mysql是基于成本(CBU)的数据库,所以小数据量不会使用索引。

2.此时还可以看一下主键索引为何会使用 ,使用SELECT id,status,name FROM user ignore index(idx_status) where id in (1,4); 强行不使用索引(mysql强制索引和禁止某个索引

PS:如果数据库为8.0版本,还可以使用隐藏索引特性
MySQL8.0版本特性

14条数据时:

在这里插入图片描述
在这里插入图片描述
使用ignore idex(pri)强行不使用主键索引:
在这里插入图片描述
在这里插入图片描述

65条数据时

在这里插入图片描述

使用ignore idex(pri)强行不使用主键索引
在这里插入图片描述
由于前面是用的对照组,但是没有设置索引毕竟是不同的表,可能会造成结果不准确,所以在知道了强制使用/不试用索引的用法后,重新测了一下,不使用普通索引的成本是13.999,而之前使用对照组(user2)是13.799就是13.999,没有影响
在这里插入图片描述
最终结果:就应该是13.999,前面建表user2少了条数据,只有64条,才会是13.799,65条是13.999,数据已修改。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值