继续创造,加速成长!这是我参加「日新计划 6 月更文挑战」的第12天,点击查看活动概况
为了验证 MySQL 中哪些状况下会导致索引失效,咱们能够凭借 explain 执行计划来剖析索引失效的详细场景。
explain 运用如下,只需要在查询的 SQL 前面添加上 explain 关键字即可,如下图所示: 而以上查询成果的列中,咱们最主要调查 key 这一列,key 这一列表明实际运用的索引,假如为 NULL 则表明未运用索引,反之则运用了索引。
以上所有成果列阐明如下:
- id — 选择标识符,id 越大优先级越高,越先被执行;
- select_type — 表明查询的类型;
- table — 输出成果集的表;
- partitions — 匹配的分区;
- type — 表明表的衔接类型;
- possible_keys — 表明查询时,或许运用的索引;
- key — 表明实际运用的索引;
- key_len — 索引字段的长度;
- ref— 列与索引的比较;
- rows — 大概估算的行数;
- filtered — 按表条件过滤的行百分比;
- Extra — 执行状况的描绘和阐明。
其间最重要的便是 type 字段,type 值类型如下:
-
all — 扫描全表数据;
-
index — 遍历索引;
-
range — 索引规模查找;
-
index_subquery — 在子查询中运用 ref;
-
unique_subquery — 在子查询中运用 eq_ref;
-
ref_or_null — 对 null 进行索引的优化的 ref;
-
fulltext — 运用全文索引;
-
ref — 运用非仅有索引查找数据;
-
eq_ref — 在 join 查询中运用主键或仅有索引相关;
-
const — 将一个主键放置到 where 后边作为条件查询, MySQL 优化器就能把这次查询优化转化为一个常量,如何转化以及何时转化,这个取决于优化器,这个比 eq_ref 效率高一点。
创立测验表和数据
为了演示和测验那种状况下会导致索引失效,咱们先创立一个测验表和相应的数据:
-- 创立表 drop table if exists student; create table student( id int primary key auto_increment comment '主键', sn varchar(32) comment '学号', name varchar(250) comment '名字', age int comment '年纪', sex bit comment '性别', address varchar(250) comment '家庭地址', key idx_address (address), key idx_sn_name_age (sn,name,age) )ENGINE=InnoDB DEFAULT CHARSET=utf8; -- 添加测验数据 insert into student(id,sn,name,age,sex,address) values(1,'cn001','张三',18,1,'高老庄'), (2,'cn002','李四',20,0,'花果山'), (3,'cn003','王五',50,1,'水帘洞');
当前表中总共有 3 个索引,如下图所示:
PS:本文以下内容根据 MySQL 5.7 InnoDB 数据引擎下。
索引失效状况1:非最左匹配
最左匹配准则指的是,以最左边的为起点字段查询能够运用联合索引,否则将不能运用联合索引。 咱们本文的联合索引的字段次序是 sn + name + age,咱们假定它们的次序是 A + B + C,以下联合索引的运用状况如下: 从上述成果能够看出,假如是以最左边开端匹配的字段都能够运用上联合索引,比方:
-
A+B+C
-
A+B
-
A+C
其间:A 等于字段 sn,B 等于字段 name,C 等于字段 age。
而 B+C 却不能运用到联合索引,这便是最左匹配准则。
索引失效状况2:过错含糊查询
含糊查询 like 的常见用法有 3 种:
- 含糊匹配后边恣意字符:like ‘张%’
- 含糊匹配前面恣意字符:like ‘%张’
- 含糊匹配前后恣意字符:like ‘%张%’
而这 3 种含糊查询中只有第 1 种查询方法能够运用到索引,详细执行成果如下:
索引失效状况3:列运算
假如索引列运用了运算,那么索引也会失效,如下图所示:
索引失效状况4:运用函数
查询列假如运用恣意 MySQL 提供的函数就会导致索引失效,比方以下列运用了 ifnull 函数之后的执行计划如下:
索引失效状况5:类型转化
假如索引列存在类型转化,那么也不会走索引,比方 address 为字符串类型,而查询的时候设置了 int 类型的值就会导致索引失效,如下图所示:
索引失效状况6:运用 is not null
当在查询中运用了 is not null 也会导致索引失效,而 is null 则会正常触发索引的,如下图所示:
总结
导致 MySQL 索引失效的常见场景有以下 6 种:
- 联合索引不满足最左匹配准则。
- 含糊查询最前面的为不确定匹配字符。
- 索引列参加了运算。
- 索引列运用了函数。
- 索引列存在类型转化。
- 索引列运用 is not null 查询。
是非审之于己,毁誉听之于人,得失安之于数。
公众号:Java面试真题解析
面试合集:gitee.com/mydb/interv…