什么是回表查询

小伙伴们可以先看这篇文章了解下什么是聚集索引和辅助索引:Are You OK?主键、聚集索引、辅助索引,简单回顾下,聚集索引的叶子节点包含完整的行数据,而非聚集索引的叶子节点存储的是每行数据的辅助索引键 + 该行数据对应的聚集索引键(主键值)。

假设有张 user 表,包含 id(主键),name,age(普通索引)三列,有如下数据:

id	name	age
1 Jack 18
7 Alice 28
10 Bob 38
20 Carry 48

画一个比较简单比较容易懂的图来看下聚集索引和辅助索引:

  • 聚集索引:

  • 辅助索引(age):

如果查询条件为主键,则只需扫描一次聚集索引的 B+ 树即可定位到要查找的行记录。举个例子:

select * from user where id = 7;

查找过程如图中绿色所示:

如果查询条件为普通索引(辅助索引) age,则需要先查一遍辅助索引 B+ 树,根据辅助索引键得到对应的聚集索引键,然后再去聚集索引 B+ 树中查找到对应的行记录。举个例子:

select * from user where age = 28;

上述 select * 等同于 select id, age, name 对吧,id 是主键索引,age 是普通索引,而 name 并不存在于 age 索引的 B+ 树上,所以通过 age 索引查询到 id 和 age 的值之后,还需要去聚集索引上才能查到 name 的值。

如图所示,第一步,查 age 辅助索引:

第二步,查聚集索引:

这就是所谓的回表查询,因为需要扫描两次索引 B+ 树,所以很显然它的性能较扫一遍索引树更低。

什么是覆盖索引

覆盖索引的目的就是避免发生回表查询,也就是说,通过覆盖索引,只需要扫描一次 B+ 树即可获得所需的行记录。

如何实现覆盖索引

上文解释过,下面这个 SQL 语句需要查询两次 B+ 树:

select * from user where age = 28;

我们将其稍作修改,使其只需要查询一次 B+ 树:

select id, age from user where age = 28;

之前我们的返回结果是整个行记录,现在我们的返回结果只需要 id 和 age。

id 是什么?主键索引(聚集索引),age 是什么?普通索引(辅助索引),age 索引的 B+ 树的叶子节点存储的是什么?辅助索引键 + 对应的聚集索引键

所以这条 SQL 语句只需要扫描一次 age 索引的 B+ 树就行了

这样,结合这个例子,不知道各位有没有受到启发,如何实现覆盖索引拒绝回表查询呢?

答:联合索引

我们把 age,name 设置为联合索引:

create index idx_age_name on user(`age`,`name`);

此时 age 和 name 作为辅助索引键都在同一棵辅助索引的 B+ 树上,所以只需扫描一次这个组合索引的 B+ 树即可获取到 id、age 和 name,这就是实现了索引覆盖

覆盖索引的常见使用场景

在下面三个场景中,可以使用覆盖索引来进行优化 SQL 语句:

1)列查询回表优化(如上面讲的例子,将单列索引 age 升级为联合索引(age, name))

2)全表 count 查询

举个例子,假设 user 表中现在只有一个索引即主键 id:

select count(age) from user;

可以用 explain 分析下这条语句,如果 Extra 字段为 Using index 时,就表示触发索引覆盖:

显然现在是没有触发覆盖索引的,我们来优化下:将 age 列设置为索引 create index idx_age on user(age),这样只需要查一遍 age 索引的 B+ 树即可得到结果:

3)分页查询

select id, age, name from user order by username limit 500, 100;

对于这条 SQL,因为 name 字段不是索引,所以在分页查询需要进行回表查询。

Using filesort 表示没有使用索引的排序,或者说表示在索引之外,需要额外进行外部的排序动作。看到这个字段就应该意识到你需要对这条 SQL 进行优化了。

使用索引覆盖优化:将 (age, name) 设置为联合索引,这样只需要查一遍 (age, name) 联合索引的 B+ 树即可得到结果。

我是小牛肉,长风破浪会有时,小伙伴们下篇文章再见

关注公众号 | 飞天小牛肉,即时获取更新

  • 博主东南大学硕士在读,携程 Java 后台开发暑期实习生,利用课余时间运营一个公众号『 飞天小牛肉 』,2020/12/29 日开通,专注分享计算机基础(数据结构 + 算法 + 计算机网络 + 数据库 + 操作系统 + Linux)、Java 技术栈等相关原创技术好文。本公众号的目的就是让大家可以快速掌握重点知识,有的放矢。关注公众号第一时间获取文章更新,成长的路上我们一起进步

  • 并推荐个人维护的开源教程类项目: CS-Wiki(Gitee 推荐项目,现已累计 1.8k+ star), 致力打造完善的后端知识体系,在技术的路上少走弯路,欢迎各位小伙伴前来交流学习 ~

  • 如果各位小伙伴春招秋招没有拿得出手的项目的话,可以参考我写的一个项目「开源社区系统 Echo」Gitee 官方推荐项目,目前已累计 900+ star,基于 SpringBoot + MyBatis + MySQL + Redis + Kafka + Elasticsearch + Spring Security + ... 并提供详细的开发文档和配套教程。公众号后台回复 Echo 可以获取配套教程,目前尚在更新中。

你的 SQL 还在回表查询吗?快给它安排覆盖索引的更多相关文章

  1. mysql中的回表查询与索引覆盖

    了解一下MySQL中的回表查询与索引覆盖. 回表查询 要说回表查询,先要从InnoDB的索引实现说起.InnoDB有两大类索引,一类是聚集索引(Clustered Index),一类是普通索引(Sec ...

  2. (MYSQL)回表查询原理,利用联合索引实现索引覆盖

    一.什么是回表查询? 这先要从InnoDB的索引实现说起,InnoDB有两大类索引: 聚集索引(clustered index) 普通索引(secondary index) InnoDB聚集索引和普通 ...

  3. MySQL优化:如何避免回表查询?什么是索引覆盖? (转)

    数据库表结构: create table user ( id int primary key, name varchar(20), sex varchar(5), index(name) )engin ...

  4. MySQL 回表查询 & 索引覆盖优化

    回表查询 先通过普通索引的值定位聚簇索引值,再通过聚簇索引的值定位行记录数据 建表示例 mysql> create table user( -> id int(10) auto_incre ...

  5. MySQL回表查询

    一.MySQL索引类型 1.普通索引:最基本的索引,没有任何限制 2.唯一索引(unique index):索引列的值必须唯一,但是允许为空 3.主键索引:特殊的唯一索引,但是不允许为空,一般在建表的 ...

  6. Oracle总结【SQL细节、多表查询、分组查询、分页】

    前言 在之前已经大概了解过Mysql数据库和学过相关的Oracle知识点,但是太久没用过Oracle了,就基本忘了...印象中就只有基本的SQL语句和相关一些概念....写下本博文的原因就是记载着Or ...

  7. 2.2 Oracle之DML的SQL语句之多表查询以及组函数

    一.SQL的多表查询: 1.左连接和右连接(不重要一方加(+)) SELECT e.empno,e.ename,d.deptno,d.dname,d.loc FROM emp e,dept d WHE ...

  8. SQL数据库的多表查询

    多表查询分为 内.外连接 外连接分为左连接(left join 或left outer join).右连接(right join 或者 right outer join).和完整外部连接 (full ...

  9. SQL语句 自连表查询。inner join用法,partition by ,列转行查询

    use mydb1 go -- 表T_Employee2 -- Id Name Position Dept -- 1 张三 员工 市场部 -- 2 李四 经理 销售部 -- 3 王五 经理 市场部 - ...

随机推荐

  1. 基于MD5+RSA算法实现接口调用防扯皮级鉴权

    概述 最近项目中需要对第三方开发接口调用,考虑了一下,准备采用MD5+RSA算对请求数据进行签名,来达到请求鉴权,过滤非法请求的目标. 数字签名采用MD5+RSA算法实现.RSA私钥要严格保密并提供安 ...

  2. DC-5靶机

    仅供个人娱乐 靶机信息 下载地址:http://www.five86.com/downloads/DC-5.zip 一.主机扫描 arp-scan -l nmap -p 1-65535 -A  -sV ...

  3. JSP的执行原理、JSP的内置对象、四大作用域解析、MVC模式理解>从零开始学JAVA系列

    目录 JSP的执行原理.JSP的内置对象.四大作用域解析.MVC模式理解 JSP的执行原理 这里拿一个小例子来解析JSP是如何被访问到的 首先将该项目部署到tomcat,并且通过tomcat启动 通过 ...

  4. 什么是CIDR?

    英文缩写: CIDR (Classless InterDomain Routing) 中文译名: 无类别域间路由选择 IP地址有"类"的概念,/8掩码是A类,/16掩码是B类,/2 ...

  5. 还有更惨的吗?字节面经,美团,网易,招银,360全部在HR前一面挂了

    最近一朋友向我吐槽去年的秋招,字节面经,美团,网易,招银,360全部在HR前一面挂了,实在是有点惨.我把他语无伦次的话做了一个整理: 最近真的很暴躁,控制不住自己陷入情绪低落胡思乱想,每天都是在希望失 ...

  6. TestNG注释@BeforeGroups与@AfterGroups不执行的处理

    在学习TestNG框架注解时发现在执行以下的代码 package com.groups; import org.testng.annotations.AfterGroups; import org.t ...

  7. .Net Core+分布式配置中心(AgileConfig)

    GitHub上AgileConfig非常详细,以下只是本人学习过程的整理 一.介绍 1.参考地址 https://github.com/dotnetcore/AgileConfig https://w ...

  8. [TensorFlow2.0]-学习率 激活函数 损失函数

    本人人工智能初学者,现在在学习TensorFlow2.0,对一些学习内容做一下笔记.笔记中,有些内容理解可能较为肤浅.有偏差等,各位在阅读时如有发现问题,请评论或者邮箱(右侧边栏有邮箱地址)提醒. 若 ...

  9. 跟我一起写 Makefile(十二)

    隐含规则 ---- 在我们使用Makefile时,有一些我们会经常使用,而且使用频率非常高的东西,比如,我们编译C/C++的源程序为中间目标文件(Unix下是[.o]文件,Windows下是[.obj ...

  10. erlang学习笔记

    安装 Ubuntu Server上: sudo apt-get install erlang 如果安装时下载 太慢,可手工下载deb包( esl-erlang_16.a-rc1_ubuntu_prec ...