0
点赞
收藏
分享

微信扫一扫

MySQL--索引失效--原因/解决方案


简介

        本文介绍数据库什么时候会索引失效以及如何避免索引失效。

        这个问题也是Java后端面试中常见的问题。

失效的场景


LIKE 以%或者_开头

  1. %和_这两个是模糊匹配,如果放在开头则不走索引。


OR 语句前后没有同时使用索引
  1. 当OR 左右查询字段只有一个是索引,该索引失效,只有当OR 左右查询字段均为索引时,才会生效。

联合索引没遵循最左前缀原则

索引列数据类型出现隐式转化
  1. varchar不加单引号的话可能会自动转换为int型,使索引无效,产生全表扫描。
    例如:tb1表中name字段是字符串类型


    1. 索引失效:SELECT * FROM tb1 WHERE name = 123
    2. 索引有效:SELECT * FROM tb1 WHERE name = '123'



索引列使用 IS NULL 或 IS NOT NULL

  1. 原因:索引无法通过空值计算出存储它的位置。
  2. 解决方法:


    1. 法1:把NULL值转为一个特定的值,在WHERE中检索时,用该特定值查找
    2. 法2:建立一个联合索引。例如:create index ind_a on table(col1,1); 通过在复合索引中指定一个非空常量值,而使构成索引的列的组合中,不可能出现全空值。




索引列使用NOT,<>,!=

  1. 不等操作符永远不会用到索引,对它的处理只会产生全表扫描。
  2. 优化方法: key<>0 改为 key>0 OR key<0。


对索引列进行计算或使用函数

  1. 原因:索引是针对原值建的二叉树,将列值计算后,原来的二叉树就用不上了。
  2. 示例:


    1. SELECT * FROM t WHERE id*3=3000
    2. SELECT * FROM t WHERE ABS(id)=3000




ORDER BY使用错误

全表扫描速度比索引速度快

  1. 此时mysql会使用全表扫描,索引失效。
  2. 例如:


    1. 数据量极少的表
    2. 表中索引字段数据重复率太高




WHERE 子句中使用参数(可能失效)

  1. 可能会导致索引失效,与版本有关。
  2. 原因:SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。此语句将进行全表扫描(可能):SELECT id FROM t WHERE num = @num
  3. 解决方案:强制查询使用索引:SELECT id FROM t WITH(INDEX(索引名)) WHERE num = @num



参考网址​

​​MySQL 索引未命中情况​​


举报

相关推荐

0 条评论