Mysql & index之失效

94 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

索引失效的 十大原因

1. 全值匹配

测试:

EXPLAIN select * from sys_order

输出结果:

image.png 可以看到进行了全表扫描 测试:

EXPLAIN select order_payment_type from sys_order

输出结果: image.png 在生产中尽量少使用select * 去查询。给查询频率高的字段创建索引

2. 最佳左前缀法

测试:

//创建复合索引
ALTER TABLE sys_order ADD INDEX index_name(order_create_id,order_payment_type);

EXPLAIN select * from sys_order where order_create_id="C25097"

输出结果:

image.png 按照索引的顺序进行使用,最佳左前缀法即是第一个不能边 而且中间列不能断

3. 不在所引列上做任何操作(计算 函数 or 类型转换)会导致索引失效而转向全表扫描

测试:

EXPLAIN select * from sys_order where order_create_id="C25097" or order_payment_type="无"

输出结果: image.png 可以看到 添加 or 条件后 索引失效 测试:添加函数

EXPLAIN select * from sys_order where  left(order_create_id,4)="付款"

输出结果: image.png 可以看到 索引失效

4. 存储引擎不能使用索引中范围条件右边的列

测试三个索引:

EXPLAIN select * from sys_order where order_create_id="C25097" 
and order_entering_userid = 25 and order_payment_type="企业店付款"

输出结果: image.png 这里我们可以看到 key_len的值 为777

测试添加范围>:

EXPLAIN select * from sys_order where order_create_id="C25097" 
and order_entering_userid > 25 and order_payment_type="企业店付款"

输出结果: image.png 我们发现 key_len的数值为 772

测试前两个索引:

EXPLAIN select * from sys_order where order_create_id="C25097"  and order_entering_userid = 25 

输出结果: image.png 可以看到我们前两个索引的key_len的值为772 由此我们可以看到范围条件后 所引列并没有生效。

5. 计量使用覆盖索引(只访问索引的查询(所引列和查询类一致)),减少select *

测试按需索取字段:

EXPLAIN select order_create_id from sys_order where order_create_id="C25097"  and order_entering_userid = 25 

输出结果: image.png 测试 查询全部:

EXPLAIN select * from sys_order where order_create_id="C25097"  and order_entering_userid = 25 

输出结果: image.png 由此我们可以看到 按需索取比* 新能更加强大

6. mysql在使用不等于(!= 或者<>) 的时候无法使用索引会导致 全表扫描

测试:

EXPLAIN select * from sys_order where order_create_id!="C25097" 

输出结果: image.png 由此我们可以看到索引失效

7. is null,is not null 也无法使用索引

测试:

EXPLAIN select * from sys_order where order_create_id is not null

输出结果:

image.png 理论上有使用但是实际上key为空 所以索引失效

8. like以通配符开头(’%abc‘)mysql 索引失效变成全表扫描

测试 左右都有%:

EXPLAIN select * from sys_order where order_create_id like "%C%"

输出结果: image.png 可以看到索引失效 测试 只有左边有%:

EXPLAIN select * from sys_order where order_create_id like "%C"

输出结果:

image.png 可以看到索引失效 测试 只有右边有%:

EXPLAIN select * from sys_order where order_create_id like "C%"

输出结果:

image.png 可以看到索引生效了,但是实际开发中 左右都有% 更为常见 测试 使用复合索引:

EXPLAIN select order_create_id,order_entering_userid,order_payment_type 
from sys_order where order_create_id like "%C%"

输出结果:

image.png 可以看到 索引并没有失效。注意复合索引不能有复合索引列外的列。

9. 字符串不加单引号索引失效

测试 varchar类型不加引号:

EXPLAIN select * from sys_order where order_create_id = 25097

输出结果: image.png 可以看到 索引失效实际并没有使用索引 测试 varchar类型加引号:

EXPLAIN select * from sys_order where order_create_id = "25097"

输出结果:

image.png 可以看到索引生效了

10. 少用 or,用它来连接时会导致索引失效

测试:

EXPLAIN select * from sys_order 
where order_create_id = "25097" or order_entering_userid = 25087

输出结果:

image.png

可以看到索引失效了

实践是检验真理的唯一方法! 明天见🥰🥰🥰