面试题: MySQL 索引失效的10大原因
个人博客网:https://wushaopei.github.io/ (你想要这里多有)
1、建表:
CREATE TABLE staffs (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR (24) NOT NULL DEFAULT '' COMMENT '姓名',
age INT NOT NULL DEFAULT 0 COMMENT '年龄',
pos VARCHAR (20) NOT NULL DEFAULT '' COMMENT '职位',
add_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间') CHARSET utf8 COMMENT '员工记录表' ;
)
2、插入数据
INSERT INTO staffs(NAME,age,pos,add_time) VALUES('z3',22,'manager',NOW());
INSERT INTO staffs(NAME,age,pos,add_time) VALUES('July',23,'dev',NOW());
3、创建索引
ALTER TABLE staffs ADD INDEX idx_staffs_nameAgePos(NAME, age, pos);
基本表信息:
mysql> desc staffs;
+----------+-------------+------+-----+-------------------+-------------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+-------------------+-------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| NAME | varchar(24) | NO | MUL | | |
| age | int(11) | NO | | 0 | |
| pos | varchar(20) | NO | | | |
| add_time | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
+----------+-------------+------+-----+-------------------+-------------------+
5 rows in set
mysql> select * from staffs;
+----+------+-----+---------+---------------------+
| id | NAME | age | pos | add_time |
+----+------+-----+---------+---------------------+
| 1 | z3 | 22 | manager | 2020-01-22 21:46:31 |
| 2 | July | 23 | dev | 2020-01-22 21:46:31 |
| 3 | h4 | 22 | manager | 2020-01-22 21:57:38 |
| 4 | Juue | 43 | dev | 2020-01-22 21:57:38 |
| ................. |
+----+------+-----+---------+---------------------+
198 rows in set
show index from staffs;
+--------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| staffs | 0 | PRIMARY | 1 | id | A | 2 | NULL | NULL | | BTREE | | | YES | NULL |
| staffs | 1 | idx_staffs_nameAgePos | 1 | NAME | A | 2 | NULL | NULL | | BTREE | | | YES | NULL |
| staffs | 1 | idx_staffs_nameAgePos | 2 | age | A | 2 | NULL | NULL | | BTREE | | | YES | NULL |
| staffs | 1 | idx_staffs_nameAgePos | 3 | pos | A | 2 | NULL | NULL | | BTREE | | | YES | NULL |
+--------+------------+-----------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
4 rows in set
1、全值匹配我最爱
2、最佳左前缀法则
- 如果索引了多列,要遵守此规则,指的是从索引最左前列开始并且不跳过索引中的列
- 带头大哥不能死,中间兄弟不能断
mysql> explain select * from staffs where age=28 and pos='managerment';
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | staffs | NULL | ALL | NULL | NULL | NULL | NULL | 198 | 1 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set , 1 warning (0.001 sec)
3、不在索引列上做任何操作
- 计算、函数、(自动或手动)类型转换,会导致索引失效而转向全表扫描
mysql> explain select * from staffs where name= 'hu';
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | staffs | NULL | ref | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 74 | const | 1 | 100 | NULL |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
1 row in set , 1 warning (0.00 sec)
mysql> explain select * from st
affs where left(name,4)= 'hu';
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | staffs | NULL | ALL | NULL | NULL | NULL | NULL | 198 | 100 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set , 1 warning (0.00 sec)
4、存储引擎不能使用索引中范围条件右边的列
- 范围之后全失效
mysql> explain select * from staffs where name
='hu' and age=28;
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------+------+----------+-------+
| 1 | SIMPLE | staffs | NULL | ref | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 78 | const,const | 1 | 100 | NULL |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------+------+----------+-------+
1 row in set
mysql> explain select * from staffs where name='hu' and
age=28 and pos='managerment';
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------+
| 1 | SIMPLE | staffs | NULL | ref | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 140 | const,const,const | 1 | 100 | NULL |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------+
1 row in set
5、尽量使用覆盖索引(只访问索引的查询(索引列和查询列一直)),减少select *
mysql> explain select * from staffs where name='hu' and
age=28 and pos='managerment';
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------+
| 1 | SIMPLE | staffs | NULL | ref | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 140 | const,const,const | 1 | 100 | NULL |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------+
1 row in set
mysql> explain select name,age,pos
from staffs where name='hu' and age=28 and pos='managerment';
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------------+
| 1 | SIMPLE | staffs | NULL | ref | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 140 | const,const,const | 1 | 100 | Using index |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------------------+------+----------+-------------+
1 row in set
6、mysql在使用不等于(!=或<>)时候,无法使用索引导致全表扫描
mysql> explain select * from staffs where name='hu'
;
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | staffs | NULL | ref | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 74 | const | 1 | 100 | NULL |
+----+-------------+--------+------------+------+-----------------------+-----------------------+---------+-------+------+----------+-------+
1 row in set
mysql> explain select * from staffs where name!='hu' ;
+----+-------------+--------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | staffs | NULL | ALL | idx_staffs_nameAgePos | NULL | NULL | NULL | 198 | 99.49 | Using where |
+----+-------------+--------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
1 row in set
mysql> explain select * from staffs where name<>'hu' ;
+----+-------------+--------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | staffs | NULL | ALL | idx_staffs_nameAgePos | NULL | NULL | NULL | 198 | 99.49 | Using where |
+----+-------------+--------+------------+------+-----------------------+------+---------+------+------+----------+-------------+
1 row in set
从 type 列可知,使用了全表扫描,此时没有使用索引。
7、is null,is not null也无法使用索引
mysql> explain select * from staffs where name is null ;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+
1 row in set
由于该列默认不为null,所以默认在使用 is null 时type 为null
mysql> explain select * from staffs where name is not null ;
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | staffs | NULL | ALL | NULL | NULL | NULL | NULL | 198 | 100 | NULL |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set
当使用 not null 时,会进行全文扫描,查找不是null 的项,此时索引失效。
8、like以通配符开头,mysql索引失效会编程全表扫描的操作
- 百分like加右边
mysql> explain select * from staffs where name like '%hu%' ;
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | staffs | NULL | ALL | NULL | NULL | NULL | NULL | 198 | 11.11 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set
mysql> explain select * from staffs where name like '%hu' ;
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | staffs | NULL | ALL | NULL | NULL | NULL | NULL | 198 | 11.11 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set
mysql> explain select * from staffs where name like 'hu%' ;
+----+-------------+--------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
| 1 | SIMPLE | staffs | NULL | range | idx_staffs_nameAgePos | idx_staffs_nameAgePos | 74 | NULL | 1 | 100 | Using index condition |
+----+-------------+--------+------------+-------+-----------------------+-----------------------+---------+------+------+----------+-----------------------+
1 row in set
9、字符串不加单引号,索引失效
- 避免隐式类型转换
10、少用or,用它连接时索引会失效
面试题: MySQL 索引失效的10大原因的更多相关文章
- mysql索引总结(4)-MySQL索引失效的几种情况
mysql索引总结(1)-mysql 索引类型以及创建 mysql索引总结(2)-MySQL聚簇索引和非聚簇索引 mysql索引总结(3)-MySQL聚簇索引和非聚簇索引 mysql索引总结(4)-M ...
- MySQL索引失效的常见场景
当然请记住,explain是一个好习惯! MySQL索引失效的常见场景 在验证下面的场景时,请准备足够多的数据量,因为数据量少时,MySQL的优化器有时会判定全表扫描无伤大雅,就不会命中索引了. 1. ...
- 面试突击60:什么情况会导致 MySQL 索引失效?
为了验证 MySQL 中哪些情况下会导致索引失效,我们可以借助 explain 执行计划来分析索引失效的具体场景. explain 使用如下,只需要在查询的 SQL 前面添加上 explain 关键字 ...
- MySQL索引失效的几种情况
1.索引不存储null值 更准确的说,单列索引不存储null值,复合索引不存储全为null的值.索引不能存储Null,所以对这列采用is null条件时,因为索引上根本 没Null值,不能利用到索引, ...
- 【索引失效】什么情况下会引起MySQL索引失效
索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: 1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因) 注意:要想使用or,又想让索引生效,只能将or条件 ...
- 【转-mysql索引失效的几种情形】
索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: 1.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因) 注意:要想使用or,又想让索引生效,只能将or条件 ...
- 3、MySQL 索引失效的场景
索引失效的场景: 1.没有 where 条件 直接看 SQL 语句 2.where 条件中所在的列没有建立索引 show index from t; 3.从表中取得数据超过某个阈值.通常认为是 ...
- MySQL索引失效之隐式转换
常见索引失效: 1. 条件索引字段"不干净":函数操作.运算操作 2. 隐式类型转换:字符串转数值:其他类型转换 3. 隐式字符编码转换:按字符编码数据长度大的方向转换,避免数据截 ...
- MySQL 索引失效-模糊查询,最左匹配原则,OR条件等。
索引失效 介绍 索引失效就是我们明明在查询时的条件为索引列(包括自己新建的索引),但是索引不能起效,走的是全表扫描.explain 后可查看type=ALL. 这是为什么呢? 首先介绍有以下几种情况索 ...
随机推荐
- 仿站-获取网站的所有iconfont图标
在仿站过程中,网站的iconfont查找非常浪费时间,这里教大家一次性获取网站iconfont的方法 1.打开 开发者工具 在element中搜索font-face,结果如下,复制font-face所 ...
- 《C程序设计语言》 练习2-3
问题描述 < class="title-article"> 练习2-3 编写函数htoi(s),把由16进制数字组成的字符串(包含可选的前缀0X或0x)转换成与之等价的 ...
- Leetcode_236. 二叉树的最近公共祖先
求二叉树的LCA code /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *le ...
- ubuntu 1604升级到ubuntu 1804无法忽视的细节问题(亲测有效)
升级ubuntu系统,遇到很多问题,可能你在升级的时候也会碰到,希望对你有所帮助: 文章目录 1 常规升级过程 2 更改过源 3 无法全部更新 4 其他的问题 5 升级成功 6 无法进入gnome 6 ...
- 在ef core中使用postgres数据库的全文检索功能实战
起源 之前做的很多项目都使用solr/elasticsearch作为全文检索引擎,它们功能全面而强大,但是对于较小的项目而言,构建和维护成本显然过高,尤其是从关系数据库/文档数据库到全文检索引擎的数据 ...
- layui批量传值到后台操作时出现传值为空的问题
如图,前台的样子,data的参数为 [ {"good_id":1,"good_name":"标样-总磷","good_num&qu ...
- Redis学习笔记(十) 客户端
Redis服务器是典型的一对多服务器程序:一个服务器可以与多个客户端建立网络连接,每个客户端可以向服务器发送命令请求,而服务器则接收并处理客户端发送的命令请求,并向客户端返回命令回复. 通过使用由I/ ...
- python实现简易工资管理系统(Salary Manage)源码
一.需求: 1.导入文件读取员工的信息和工资信息,最后将增加.删除或修改的员工工资信息写入原来的文件中 2.能够实现员工工资信息的增删改查 3.当增加和修改员工信息时用户用空格分隔员工姓名和薪资 4. ...
- Oracle 大数据查询优化方法
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- [Unity UGUI序列帧]简单实现序列帧的播放
在使用序列帧之前需要准备好序列帧的图集,打图集的操作参考 [Unity UGUI图集系统]浅谈UGUI图集使用 准备好序列帧图集,序列帧的播放原理就是获取到图集中的所有图片,然后按照设置的速度按个赋值 ...