面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?

一、什么时候不推荐使用索引

  • 如果你的表设计了索引,但是在哪些情况下这些索引的使用会失效?

情景①

  • 数据唯一性差(一个字段的取值只有几种时)的字段不要使用索引
  • 比如性别,只有两种可能数据。意味着索引的二叉树级别少,多是平级。这样的二叉树查找无异于全表扫描

情景②

  • 频繁更新的字段不要使用索引
  • 比如logincount登录次数,频繁变化导致索引也频繁变化,增大数据库工作量,降低效率

情景③

  • 字段不在where语句出现时不要添加索引,只有在where语句出现,mysql才会去使用索引
  • 如果where后含IS NULL /IS NOT NULL/ like ‘%输入符%’等条件,不建议使用索引

情景④

  •  where子句里对索引列使用不等于(<>),使用索引效果一般

二、什么时候索引会失效?

  • 索引失效是指MySQL索引设置了索引,但是SQL语句执行的时候并没有使用到索引

条件中带有or

  • 规则为:
    • or语句两侧只有一个使用了索引,那么索引就会失效
    • 只有当or语句前后都有索引,那么才能根据索引进行查询
  • 例如,现在我们有这样一张表,其中:
    • id字段为主键(有主键索引)
    • user_name字段有普通索引(索引名为user_name)
    • age字段无索引
-- 创建表
create table student (
    id int not null,
    user_name varchar(30) not null,
    age int not null,
    primary key(id),
    index(user_name)
);

-- 插入几条数据
insert into student value(1,"C",18),(2,"C++",17),(3,"Linux",16);

面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?_第1张图片

  • 演示案例如下:
    • 第一条SQL:id字段为主键索引,因此使用主键索引进行查询
    • 第二条SQL:user_name字段为普通索引,因此使用普通索引进行查询
    • 第三条SQL:虽然id有索引,但是由于age没有索引,因此索引失效
    • 第四条SQL:同上,因此索引失效
-- 会使用索引
explain select * from student where id = 1\G

-- 会使用索引
explain select * from student where user_name = 'C++'\G

-- 不会使用索引
explain select * from student where id= 1 or age=17\G

-- 不会使用索引
explain select * from student where age = 18 or user_name = 'C'\G

面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?_第2张图片

复合(组合)索引没有完全使用

  • 对于复合索引(组合索引),如果没有使用左边的列,那么组合索引也失效

like查询以%开头

  • 如果查询时,like是以%开头的,那么索引就会失效
  • 例如:
-- 不会使用索引
explain select * from student where user_name like '%inux'\G

-- 会使用索引
explain select * from student where user_name = 'C%'\G

面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?_第3张图片

存在索引列的数据类型隐形转换

  • 存在索引列的数据类型隐形转换,则用不上索引
  • 比如列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则可能会自动转换为int,不使用索引
  • 演示案例:
-- 使用索引
explain select * from student where user_name='0'\G

-- 不使用索引
explain select * from student where user_name=0\G

面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?_第4张图片

在索引列上使用 IS NULL 或 IS NOT NULL操作

  • 索引是不索引空值的,所以这样的操作不能使用索引。可以用其他的办法处理,例如:数字类型,判断大于0;字符串类型设置一个默认值,判断是否等于默认值即可
  • 演示案例:
-- 不会使用索引
explain select * from student where user_name is not null\G

-- 不会使用索引
explain select * from student where user_name is null\G

面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?_第5张图片

在索引字段上使用not、<>、!=

  • 不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描
  • 优化方法: key<>0 改为 key>0 or key<0
  • 演示案例:
-- 会使用索引
explain select * from student where id >0 or id <1\G

-- 不会使用索引
explain select * from student where user_name !=0\G

面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?_第6张图片

对索引字段进行计算操作

  • 如果where语句中对字段进行了计算操作,那么也不会使用索引
  • 演示案例:
-- 会使用索引
explain select * from student where id =1\G

-- 不会使用索引
explain select * from student where id-1 =1\G

-- 不会使用索引
explain select * from student where id=id+1\G

面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?_第7张图片

字段上使用函数

  • 在字段上使用函数时,那么也不会使用索引
  • 演示案例:
-- 不会使用索引, left()函数返回字符串左边的n个字符
explain select * from student where left(user_name,1) ='C'\G

面试冲刺:19---MySQL什么时候不推荐使用索引,什么时候索引会失效?_第8张图片

全表扫描比使用索引快时

  • 如果你的SQL语句查询的内容占整个表的大部分内容时,那么MySQL会自动优化不使用索引,而直接全表扫描
  • 因为当查询的内容占表的大部分行时,可能全表扫描比使用索引的速度还要快,这是MySQL内部优化的
  • 当然,你也可以强制使用索引进行查询
select * from student force index(id) where id > 2;
  • 这个现象在另一篇文章也介绍过:https://blog.csdn.net/qq_41453285/article/details/107747295

你可能感兴趣的:(面试冲刺,MySQL的索引何时会失效?)