MySQL 05 深入浅出索引(下)

覆盖索引

假设要执行一条语句:

sql 复制代码
select * from T where k between 3 and 5;

初始对列k建立了索引,表中数据为:

那么其执行流程为:

  • 在k索引树上找到k=3的记录,取得ID=300;

  • 到ID索引树查到ID=300对应的记录。

  • 在k索引树上找到下一个值k=5的记录,取得ID=500;

  • 到ID索引树查到ID=500对应的记录。

  • 在k索引树上找到下一个值k=6,发现不满足条件。

这个过程中,发生了回表。假如建立的索引能"覆盖"我们的查询需求,就不需要回表,这种索引称为覆盖索引。比如在上面的查询语句中,若查询的是列k而不是*,就是一个覆盖索引。

需要注意的是,在引擎内部使用覆盖索引在索引k上其实能读到R3-R5三个记录,但是由于Server层只会从引擎得到两条记录,因此MySQL认为扫描行数为2。

最左前缀原则

B+树这种索引结构,可以利用索引的最左前缀,来定位记录。

比如建立了(name,age)的联合索引:

当要查询name="张三",可以快速定位到ID4,然后向后遍历。

当要查询where name like "张%",也能用上这个索引,定位到ID3,然后向后遍历。

因此,索引的最左前缀可以是联合索引的最左N个字段,也可以是字符串索引的最左M个字符。

索引下推

还是假设建立了(name,age)的联合索引,现在有一条SQL语句如下:

sql 复制代码
select * from tuser where name like '张%' and age=10 and ismale=1;

由最左前缀原则,这条语句能用上name的索引。

而其他条件的判断:

  • 在MySQL 5.6前,只能从找到的第一个记录ID3开始一个个回表,到主键索引上找出数据行,再对比后面两个字段。

  • MySQL 5.6引入了索引下推优化,可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤不满足条件的记录,减少回表次数。

两者的比较如下,第一张图是无索引下推,第二张图是有索引下推,箭头表示回表:

参考资料:极客时间专栏《MySQL实战45讲》https://time.geekbang.org/column/intro/100020801?tab=catalog

相关推荐
周杰伦fans3 小时前
Navicat - 连接 mysql 、 sqlserver 数据库 步骤与问题解决
数据库·mysql·sqlserver
csdn_aspnet3 小时前
如何在 Ubuntu 24.04/22.04/20.04 上安装 MySQL 8.0
linux·mysql·ubuntu
最好结果4 小时前
MyBatis 精确查询逗号分隔字符串
mysql·mybatis·1024程序员节
苹果醋34 小时前
学习札记-Java8系列-1-Java8新特性简介&为什么要学习Java8
java·运维·spring boot·mysql·nginx
zz-zjx5 小时前
MySQL 索引深度指南:原理 · 实践 · 运维(适配 MySQL 8.4 LTS)
运维·数据库·mysql
布朗克1685 小时前
MySQL 运算符详细说明
数据库·mysql·运算符·1024程序员节
码力引擎7 小时前
【零基础学MySQL】第一章:MySQL介绍与安装
数据库·mysql·1024程序员节
Sam_Deep_Thinking7 小时前
MySQL 8 索引与 B+ 树-初浅理解
mysql
235167 小时前
【MySQL】慢查寻的发现和解决优化(思维导图版)
java·后端·sql·mysql·职场和发展·数据库开发·数据库架构
hweiyu008 小时前
Node.js+Koa2+MySQL 打造前后端分离项目(视频教程)
数据库·mysql·node.js