索引失效
介绍索引失效就是我们明明在查询时的条件为索引列(包括自己新建的索引),但是索引不能起效,走的是全表扫描 。explain 后可查看type=ALL 。
这是为什么呢?
首先介绍有以下几种情况索引会出现失效:
- 当我们使用了左模糊匹配和左右模糊匹配的时候,像like ‘%str’或者‘%str%’ 。
- 当我们使用联合索引没有遵守最左匹配原则的时候 。
- 当我们使用索引时对其索引字段进行计算、函数、类型转换的操作 。
- 当我们在where条件子句中使用了OR运算,同时OR前为索引列,OR后的条件不是索引列 。以上几种情况均会引起索引失效 。
下面我们来谈谈具体的原因和其中的细节1、第一种情况:左模糊匹配和左右模糊匹配我们都知道在mysql中innodb存储引擎会对我们的索引以B+树存储 。
InnoDB 存储引擎根据索引类型不同,分为聚簇索引(主键索引)和二级索引 。它们区别在于,聚簇索引的叶子节点存放的是实际数据,所有完整的用户数据都存放在聚簇索引的叶子节点,而二级索引的叶子节点存放的是主键值,而不是实际数据 。
主键索引一般来说叶子结点存储的都是数据本身 。二级索引一般来说叶子结点存储的都是数据的物理地址 。
因为索引 B+ 树是按照「索引值」有序排列存储的,只能根据前缀进行比较 。
下面看看转载:
来自:[小林Code][https://mp.weixin.qq.com/s/lEx6iRRP3MbwJ82Xwp675w]
文章插图
索引存储结构长什么样?我们先来看看索引存储结构长什么样?因为只有知道索引的存储结构,才能更好的理解索引失效的问题 。
索引的存储结构跟 MySQL 使用哪种存储引擎有关,因为存储引擎就是负责将数据持久化在磁盘中,而不同的存储引擎采用的索引数据结构也会不相同 。
MySQL 默认的存储引擎是 InnoDB,它采用 B+Tree 作为索引的数据结构,至于为什么选择B+ 树作为索引的数据结构,详细的分析可以看我这篇文章:为什么 MySQL 喜欢 B+ 树?
在创建表时,InnoDB 存储引擎默认会创建一个主键索引,也就是聚簇索引,其它索引都属于二级索引 。
MySQL 的 MyISAM 存储引擎支持多种索引数据结构,比如 B+ 树索引、R 树索引、Full-Text 索引 。MyISAM 存储引擎在创建表时,创建的主键索引默认使用的是 B+ 树索引 。
虽然,InnoDB 和 MyISAM 都支持 B+ 树索引,但是它们数据的存储结构实现方式不同 。不同之处在于:
- InnoDB 存储引擎:B+ 树索引的叶子节点保存数据本身;
- MyISAM 存储引擎:B+ 树索引的叶子节点保存数据的物理地址;
这里有一张 t_user 表,其中 id 字段为主键索引,其他都是普通字段 。
文章插图
如果使用的是 MyISAM 存储引擎,B+ 树索引的叶子节点保存数据的物理地址,即用户数据的指针,如下图:
文章插图
如果使用的是 InnoDB 存储引擎,B+ 树索引的叶子节点保存数据本身,如下图所示:
文章插图
InnoDB 存储引擎根据索引类型不同,分为聚簇索引(上图就是聚簇索引)和二级索引 。它们区别在于,聚簇索引的叶子节点存放的是实际数据,所有完整的用户数据都存放在聚簇索引的叶子节点,而二级索引的叶子节点存放的是主键值,而不是实际数据 。
经验总结扩展阅读
- MySQL 全局锁、表级锁、行级锁,你搞清楚了吗?
- golang中的nil接收器
- llinux下mysql建库、新建用户、用户授权、修改用户密码
- RedHat7.6安装mysql8步骤
- golang中的字符串
- flutter系列之:flutter中可以建索引的栈布局IndexedStack
- 究极无敌细节版 Mysql索引
- Mysql通过Canal同步Elasticsearch
- MySQL的日志文件
- 01-MySQL8主从详解