在Mysql中,什么是回表,什么是覆盖索引,索引下推?

一、什么是回表查询?

通俗的讲就是,如果索引的列在 select 所需获得的列中(因为在 mysql 中索引是根据索引列的值进行排序的,所以索引节点中存在该列中的部分值)或者根据一次索引查询就能获得记录就不需要回表,如果 select 所需获得列中有大量的非索引列,索引就需要到表中找到相应的列的信息,这就叫回表。

InnoDB聚集索引的叶子节点存储行记录,因此, InnoDB必须要有,且只有一个聚集索引:

(1)如果表定义了主键,则PK就是聚集索引;
(2)如果表没有定义主键,则第一个非空唯一索引(not NULL unique)列是聚集索引;
(3)否则,InnoDB会创建一个隐藏的row-id作为聚集索引;

先创建一张表,sql 语句如下:

create table xttblog(id int primary key, k int not null, name varchar(16),index (k)
)engine = InnoDB;

然后,我们再执行下面的 SQL 语句,插入几条测试数据。

INSERT INTO xttblog(id, k, name) VALUES(1, 2, 'xttblog'),(2, 1, '业余草'),(3, 3, '业余草公众号');

假设,现在我们要查询出 id 为 2 的数据。那么执行 select * from xttblog where ID = 2; 这条 SQL 语句就不需要回表。原因是根据主键的查询方式,则只需要搜索 ID 这棵 B+ 树。主键是唯一的,根据这个唯一的索引,MySQL 就能确定搜索的记录。

但当我们使用 k 这个索引来查询 k = 2 的记录时就要用到回表。select * from xttblog where k = 2; 原因是通过 k 这个普通索引查询方式,则需要先搜索 k 索引树,然后得到主键 ID 的值为 1,再到 ID 索引树搜索一次。这个过程虽然用了索引,但实际上底层进行了两次索引查询,这个过程就称为回表。

也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询。

我这里表里的数据量比较少,如果数据量大的话,你能很明显的看出两次查询所用的时间,很明显使用主键查询效率更高。

更多如下图:
在这里插入图片描述

(1)先通过普通索引定位到主键值id=5;
(2)在通过聚集索引定位到行记录;

这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低

小总结

使用聚集索引(主键或第一个唯一索引)就不会回表,普通索引就会回表。

二、什么是索引覆盖?

只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。

explain的输出结果Extra字段为Using index时,能够触发索引覆盖。

三、如何实现索引覆盖?

1、常见的方法是:将被查询的字段,建立到联合索引里去。
例子

create table user (
id int primary key,
name varchar(20),
sex varchar(5),
index(name)
)engine=innodb;

第一个sql:

select id,name from user where name='shenjian';

在这里插入图片描述
能够命中name索引,索引叶子节点存储了主键id,通过name的索引树即可获取id和name,无需回表,符合索引覆盖,效率较高。

Extra:Using index。

第二个sql:

select id,name,sex from user where name='shenjian';

在这里插入图片描述

能够命中name索引,索引叶子节点存储了主键id,没有储存sex,sex字段必须回表查询才能获取到,不符合索引覆盖,需要再次通过id值扫描聚集索引获取sex字段,效率会降低。

Extra:Using index condition。

如果把(name)单列索引升级为联合索引(name, sex)就不同了。


create table user1 (
id int primary key,
name varchar(20),
sex varchar(5),
index(name, sex)
)engine=innodb;

在这里插入图片描述
可以看到:

select id,name … where name=‘shenjian’;
select id,name,sex … where name=‘shenjian’;

单列索升级为联合索引(name, sex)后,索引叶子节点存储了主键id,name,sex,都能够命中索引覆盖,无需回表。

画外音,Extra:Using index。

四、哪些场景可以利用索引覆盖来优化SQL?

场景1:全表count查询优化

在这里插入图片描述
原表为:
user(PK id, name, sex);

直接:
select count(name) from user;
不能利用索引覆盖。

添加索引:
alter table user add key(name);
就能够利用索引覆盖提效。

场景2:列查询回表优化

这个例子不再赘述,将单列索引(name)升级为联合索引(name, sex),即可避免回表。

场景3:分页查询

将单列索引(name)升级为联合索引(name, sex),也可以避免回表。

五、什么是索引下推

索引下推(Index condition pushdown)简称ICP,是一种优化数据库查询的技术,它利用了数据库索引的特性,在一定条件下,在索引层面就过滤掉不需要的数据,从而减少查询时需要访问的数
据块,提高查询效率。

在普通的查询中,数据库需要先从表中读取所有的数据记录,然后再根据查询条件过滤不需要的记录,最后返回查询结果。而在索引下推中,数据库会在索引树的节点上进行条件过滤,只将满足条件的数据块返回,而不是读取整个数据记录。这样可以避免从磁盘读取不必要的数据,降低IO开销,提升查询速度。

索引下推的主要优点是减少了回表操作,即减少了访问磁盘的次数和需要传输的数据量,从而提高了查询效率和响应速度。具体来说,如果查询条件涉及到的字段都可以通过索引直接获取,而不需要回表操作,那么查询速度将大大提高。

需要注意的是,索引下推并不是适用于所有类型的查询,它涉及到查询中所使用的索引类型和查询条件的限制。通常,只有涉及到等值查询或范围查询的情况下,才能使用索引下推技术实现优化。同时,索引下推也会产生额外的开销,需要消耗更多的CPU资源,因此需要在实际应用中进行评估和优化。

MySQL的大概框架为:
在这里插入图片描述
索引下推的下推其实就是指将部分上层(服务层)负责的事情,交给了下层(引擎层)去处理。

假设有这样一个用户表:
在这里插入图片描述

创建一个联合索引(age, birthday),并查询出年龄>20,且生日为03-01的用户:select * from user where age>20 and birthday=03-01

为在没有索引下推的情况下,执行步骤如下:

  • 存储引擎根据索引查找出age>20的用户id,分别是:4,5,7
  • 存储引擎到表格中取出id in (4,5,7)的3条记录,返回给服务层
  • 服务层过滤掉不符合birthday="03-01"条件的记录,最后返回查询结果为id=4的1行记录。

如果开启了索引下推优化,执行步骤如下:

  • 存储引擎根据索引查找出age>20的用户id,并使用索引中的birthday字段过滤掉不符合birthday="03-01"条件的记录,最后得到id=4;
  • 存储引擎到表格中取出id=4的1条记录,返回给服务层;
  • 服务层过滤掉不符合birthday="03-01"条件的记录,最后返回查询结果为id=4的1行记录。
  • 启用索引下推后,把where条件由MySQL服务层放到了存储引擎层去执行,带来的好处就是存储引擎根据id到表格中读取数据的次数变少了。在上面这个例子中,没有索引下推时需要多回表查询2次。并且回表查询很可能是离散IO,在某些情况下,对数据库性能会有较大提升。

假设有这么个需求,查询表中“名字第一个字是张,性别男,年龄为10岁的所有记录”。那么,查询语句是这么写的

mysq> select * from tuser where name like '张 %' and age=10 and ismale=1;

根据前面说的“最左前缀原则”,该语句在搜索索引树的时候,只能匹配到名字第一个字是‘张’的记录(即记录ID3),接下来是怎么处理的呢?当然就是从ID3开始,逐个回表,到主键索引上找出相应的记录,再比对age和ismale这两个字段的值是否符合。

但是!MySQL 5.6引入了索引下推优化,可以在索引遍历过程中,对索引中包含的字段先做判断,过滤掉不符合条件的记录,减少回表字数。
下面图1、图2分别展示这两种情况。

在这里插入图片描述
在这里插入图片描述
图 1 中,在 (name,age) 索引里面我特意去掉了 age 的值,这个过程 InnoDB 并不会去看 age 的值,只是按顺序把“name 第一个字是’张’”的记录一条条取出来回表。因此,需要回表 4 次。

图 2 跟图 1 的区别是,InnoDB 在 (name,age) 索引内部就判断了 age 是否等于 10,对于不等于 10 的记录,直接判断并跳过。在我们的这个例子中,只需要对 ID4、ID5 这两条记录回表取数据判断,就只需要回表 2 次。

总结

如果没有索引下推优化(或称ICP优化),当进行索引查询时,首先根据索引来查找记录,然后再根据where条件来过滤记录;在支持ICP优化后,MySQL会在取出索引的同时,判断是否可以进行where条件过滤再进行索引查询,也就是说提前执行where的部分过滤操作,在某些场景下,可以大大减少回表次数,从而提升整体性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/227795.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【傻瓜级JS-DLL-WINCC-PLC交互】2.wincc使用C#开发的.net控件

思路 JS-DLL-WINCC-PLC之间进行交互,思路,先用Visual Studio创建一个C#的DLL控件,然后这个控件里面嵌入浏览器组件,实现JS与DLL通信,然后DLL放入到WINCC里面的图形编辑器中,实现DLL与WINCC的通信。然后PLC与…

微机原理_7

一、单项选择题(本大题共15小题,每小题3分,共45分。在每小题给出的四个备选项中,选出一个正确的答案,请将选定的答案填涂在答题纸的相应位置上。) 下列属于串行通信接口标准的有() A. PCI B. IDE C. USB D. EISA Intel 8086/8088…

echart 柱状图-bar

业务场景一 效果 业务组件调用代码 <template> <barCom :domId"1" :title"barComProps.title" :xAxisData"barComProps.xAxisData" :yAxisProps"barComProps.yAxisProps" :seriseData"barComProps.serise…

基于FactoryBean、实例工厂、静态工厂创建Spring中的复杂对象

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

在 vue3 中使用 Recorder 实现录音并上传(mp3、wav)兼容 PC 和移动端

一、Recorder 介绍 使用 Recorder插件可以在网页中进行录音。生成 blob 文件并可以自定义上传&#xff0c;同时&#xff0c;录音过程中会显示可视化波形&#xff0c;同时能够做到兼容PC端、Android、和iOS&#xff0c;十分好用&#xff01; Recorder github 首页 插件效果展…

深度学习回顾:七种网络

一、说明 本文 揭开CNN、Seq2Seq、Faster R-CNN 和 PPO &#xff0c;以及transformer和humg-face— 编码和创新之路。对于此类编程的短小示例&#xff0c;用于对照观察&#xff0c;或做学习实验。 二、CNN网络示例 2.1 CNN用mnist数据集 CNN 专为图像处理而设计&#xff0c;包…

学习笔记-瑞吉外卖项目实战(一)

软件开发整体介绍 软件开发流程 角色分工 软件环境 瑞吉外卖项目介绍 项目介绍 产品原型介绍 技术选型 功能架构 角色 开发环境搭建 数据 创建database reggie&#xff0c;在里面创建表&#xff1a; maven 创建springboot项目并导入相关依赖坐标&#xff1a; 我们可以在项目…

基于SSM的论文管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

wmvcore.dll丢失怎么办?解决电脑出现wmvcore.dll丢失问题5个方法

wmvcore.dll缺失5个解决方法与wmvcore.dll丢失原因及文件介绍 引言&#xff1a; 在日常使用电脑的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是wmvcore.dll缺失。wmvcore.dll是Windows Media Video编码解码相关动态链接库文件之一&#xff0c;它对…

docker安装Sentinel zipkin

文章目录 引言I Sentinel安装1.1 运行容器1.2 DOCKERFILE 参考1.3 pom 依赖1.4 .yml配置(整合springboot)II 资源保护2.1 Feign整合Sentinel2.2 CommonExceptionAdvice:限流异常处理类III zipkin引言 消息服务和请求第三方服务可不配置Sentinel。 I Sentinel安装 Sentinel …

Python Pyvis库:可视化复杂网络结构的利器

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是涛哥&#xff0c;今天为大家分享 Python Pyvis库&#xff1a;可视化复杂网络结构的利器&#xff0c;全文4000字&#xff0c;阅读大约12钟。 在数据科学和网络分析领域&#xff0c;理解和可视化复杂网络结构是…

仿制剧情吧网站源码 帝国CMS剧情介绍模板

帝国CMS7.5剧情介绍模板&#xff0c;仿制剧情吧网站的风格。该模板并非用于直接播放电影&#xff0c;而是用文字描述剧情&#xff0c;同时包含手机版。本站免费分享供站长学习研究使用。采用伪静态技术&#xff0c;无需生成HTML。出于美观考虑&#xff0c;自带数据仅供本地环境…