mysql回表查询和索引覆盖

news2024/11/27 12:58:50

作为 JAVA 开发的必备知识,了解回表查询和索引覆盖可以大大提升数据库查询的速度,也是优化数据库查询的必备知识。

1. 什么是索引?

索引(在 MySQL 中也叫“键key”)是存储引擎快速找到记录的一种数据结构,通俗来说类似书本的目录,这个比方虽然被用的最多但是也是最恰如其当的,在查询书本中的某个知识点不借助目录的情况下,往往都找的够呛,那么索引相较于数据库的重要性也可见一斑。

回表查询和索引覆盖

InnoDB索引分为两大类,一类是聚集索引(Clustered Index),一类是非聚集索引(Secondary Index)

聚集索引(聚簇索引):叶子节点中存的是整行数据,找到索引也就找到了数据,索引即数据,表中行的物理顺序与键值的逻辑(索引)顺序相同,一个表只能包含一个聚集索引。因为索引(目录)只能按照一种方法进行排序。

非聚集索引(普通索引、非聚簇索引、二级索引):非聚集索引的btree叶子节点中存储的是当行数据的PK(主键)。例如MYISAM通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因。

为什么非主键索引结构叶子结点存储的是主键值?

减少了出现行移动或者数据页分裂时二级索引的维护工作(当数据需要更新的时候,二级索引不需要修改,只需要修改聚簇索引,一个表只能有一个聚簇索引,其他的都是二级索引,这样只需要修改聚簇索引就可以了,不需要重新构建二级索引)

回表查询
回表查询顾名思义就是在数据查询过程中 MySQL 内部需要两次查询。即先定位查询数据所在表的主键值,再根据主键定位行记录。

要说回表查询,我们就要先从 InnoDB 的索引实现说起。InnoDB 索引分为两大类:聚集索引( Clustered Index )和普通索引( Secondary Index )。

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

(1)如果表定义了 PK (Primary Key,主键),那么 PK 就是聚集索引;

(2)如果表没有定义 PK,则第一个 NOT NULL UNIQUE 的列就是聚集索引。

(3)否则 InnoDB 会另外创建一个隐藏的 ROWID 作为聚集索引。

由于这种机制是直接定位行记录,因此使得基于 PK 的查询速度非常快。

InnoDB 普通索引( Secondary Index )
InnoDB 普通索引的叶子节点存储主键值(MyISAM 则是存储的行记录头指针)。

回表查询
例如:创建一个表 user_t :

CREATE TABLE `user_t` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `age` int DEFAULT '0',
  `sex` char(1) DEFAULT '0' COMMENT '用户性别(0男 1女 2未知)',
  `count` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_t_name_IDX` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb3;

​ 其中 id 为聚集索引,name 为普通索引。

为表中添加四条记录:

INSERT INTO user_t
(id, name, age, sex, count)
VALUES(1, 'zhangsan', 20, '0', 0);
INSERT INTO user_t
(id, name, age, sex, count)
VALUES(2, 'lisi', 21, '0', 0);
INSERT INTO user_t
(id, name, age, sex, count)
VALUES(3, 'xiaohong', 19, '1', 0);
INSERT INTO user_t
(id, name, age, sex, count)
VALUES(4, 'xiaohong', 18, '1', 0);

聚集索引的B+树索引(id是PK,叶子节点存储行记录):

普通索引的B+树索引(name是KEY,叶子节点存储PK值,即id):

​ 

普通索引因为无法直接定位行记录,其查询过程在通常情况下是需要扫描两遍索引树的。

select * from t where name = 'xiaohong';

explain查看执行过程是这样的:

查询的内容不再索引内,where条件为索引最左前缀,extra为null, type为ref,表明虽然用到了索引,但是没有索引覆盖,产生了回表

实际进行了2次索引扫描

 img

粉红色的路径需要扫描两遍索引树,第一遍先通过普通索引定位到主键值id=5,然后第二遍再通过聚集索引定位到具体行记录。这就是所谓的回表查询,即先定位主键值,再根据主键值定位行记录,性能相对于只扫描一遍聚集索引树的性能要低一些。

怎么判断是否出现了回表
1,在 explain(执行计划)Extra 中看到了 Using Where,代表是按照 where 条件进行了过滤,和是否走索引、回表无必然的关系。
2,在 explain(执行计划)Extra 中是 Using Index & Using Where,表示 select 的数据在索引中能找到,但需要根据 where 条件过滤,这种情况也不会用到回表。
3,只有在使用了索引,且在 explain(执行计划)Extra 中看到了 Using Where 或者Extra是null的情况下,才代表回表查询数据。

索引覆盖

索引覆盖是一种避免回表查询的优化策略。具体做法就是将要查询的数据作为索引建立普哦,那个索引(可以是单列索引,也可以一个索引语句定义所有要查询的列,即联合索引),这样就可以直接返回索引中的数据,不需要再通过聚集索引去定位行记录,避免了回标的情况发生。

1.什么是覆盖索引?

1)只需要在一棵索引树上就可以获取sql所需所有的列数据,不需要回表,较之回表速度要更快。

2)explain输出结果extra字段为Using index时,触发了索引覆盖。

定义
如果一个索引覆盖(包含)了所有需要查询的字段的值,这个索引就是覆盖索引。

覆盖索引的定义与注意事项

如果一个索引覆盖(包含)了所有需要查询的字段的值,这个索引就是覆盖索引。因为索引中已经包含了要查询的字段的值,因此查询的时候直接返回索引中的字段值就可以了,不需要再到表中查询,避免了对主键索引的二次查询,也就提高了查询的效率。

要注意的是,不是所有类型的索引都可以成为覆盖索引的。因为覆盖索引必须要存储索引的列值,而哈希索引、空间索引和全文索引等都不存储索引列值,索引MySQL只能使用B+Tree索引做覆盖索引。

怎么判断索引覆盖查询
当发起一个被索引覆盖的查询(索引覆盖查询)时,在 explain(执行计划)的 Extra 中可以看到 Using Index 的信息。

索引覆盖的优点

索引条目通常远小于数据行的大小,因为覆盖索引只需要读取索引,极大地减少了数据的访问量。
索引是按照列值顺序存储的,对于IO密集的范围查找会比随机从磁盘读取每一行数据的IO小很多。
一些存储引擎比如MyISAM在内存中只缓存索引,数据则依赖操作系统来缓存,因此要访问数据的话需要一次系统调用,使用覆盖索引则避免了这一点。
由于InnoDB的聚簇索引,覆盖索引对InnoDB引擎下的数据库表特别有用。因为InnoDB的二级索引在叶子节点中保存了行的主键值,如果二级索引能够覆盖查询,就避免了对主键索引的二次查询。

哪些场景适合使用索引覆盖来优化SQL

当不需要查询整行记录时;

 全表count查询优化;

Limit分页查询;

哪些情况下不要建索引

表记录太少
经常增删改的表或者字段(如用户余额)
Where条件里用不到的字段不创建索引
过滤性不好的不适合建索引(如性别)
 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是Hystrix?简述实现机制

分布式容错框架 阻⽌故障的连锁反应,实现熔断 快速失败,实现优雅降级提供实时的监控和告警资源隔离: 线程隔离,信号量隔离 线程隔离:Hystrix会给每⼀个Command分配⼀个单独的线程池,这样在进⾏单个服务调⽤…

深入react源码看setState究竟做了什么?

前言 在深究 React 的 setState 原理的时候,我们先要考虑一个问题:setState 是异步的吗? 首先以 class component 为例,请看下述代码(demo-0) class App extends React.Component {state {count: 0}hand…

LQ0272 矩形运算【计算几何】

题目来源:蓝桥杯2012初赛 Java A组H题 题目描述 在编写图形界面软件的时候,经常会遇到处理两个矩形的关系。 如图 1 所示,矩形的交集指的是:两个矩形重叠区的矩形,当然也可能不存在(参看图 2 &#xff09…

Linux下C语言UDP协议通信实践

UDP和TCP协议一样,都是传输层协议。是无连接的,不安全的,报式传输层协议,通信过程默认也是阻塞的。其通信特点主要如下: (1)不需要建立连接 ,所以不需要进行 connect () 操作 &…

国产操作系统之凝思磐石安装

一、凝思磐石操作系统简介 安全性是凝思磐石安全服务平台软件V2.4的主要特征,充分结合凝思科技独有技术与国内外多项安全标准的要求,在操作系统和应用程序的各个层次进行安全增强,使系统成为安全的有机整体。主要安全机制有以下几点&#xff…

高校房产管理现状及数图互通解决方案?

高校拥有大量的房产土地资源、公共设施、公有住房等,是高校开展各类教学、科研的基础场所,也是学校国有资产不可缺少的一部分。但是在管理过程中,存在着较多的困难与问题: 1.房地产的有效利用率不高 2.房地产管理信息化速度较慢…

异常解决!针对文件I/O写入操作时FileNotFoundException异常的修复

一. 异常问题 I/O对于在Java学习路上的初学者来说,简直就是一道长长的坎儿。我们在使用I/O的过程中,会有许多的异常需要处理,并且其中还带有一系列的验证逻辑在其中。如果在学习过程中,我们的基础打得不牢靠,那么可能…

如何在Xshell上运行一个C文件?

1.设置XTP服务器配置 按下图点击,创建一个新的连接: 如图所示,创建成功 2.Xshell界面创建 如图界面,就说明成功了 3.在电脑任意位置保存一个txt文件,注意扩展名要改成.c 4.在Xftp中导入刚写好的.c文件 如图&#xff…

pom报红

若是从其他地方导入的新工程,右边 maven 管理工具中 dependencies 若出现红色波浪线。通常用以下方式尝试解决。 第一步 0.导入外部项目,先配置jdk。 1.(检查maven仓库配置是否正确)File --> settings 输入maven&#xff0…

爆料,前华为微服务专家纯手打500页落地架构实战笔记,已开源

开篇 微服务是现代系统中非常受关注的“焦点”,越来越多地分布式系统都纷纷采用微服务的设计理念来演进其架构模型。随着微服务应用规模的增长,治理膨胀的系统会越来越困难。比起微服务设计和拆分,如何能够更好地治理大规模的微服务&#xf…

LeetCode每日一题——813. 最大平均值和的分组

LeetCode每日一题系列 题目:813. 最大平均值和的分组 难度:普通 文章目录LeetCode每日一题系列题目示例思路题解题目 给定数组 nums 和一个整数 k 。我们将给定的数组 nums 分成 最多 k 个相邻的非空子数组 。 分数 由每个子数组内的平均值的总和构成…

制作一个简单HTML西安旅游网页(HTML+CSS)

👨‍🎓学生HTML静态网页基础水平制作👩‍🎓,页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码,这是一个不错的旅游网页制作,画面精明,排版整洁,内容…

Java以form-data(表单)的形式调用第三方接口

Java以form-data(表单)的形式调用第三方接口前言本文目标用到的类工具类及测试信息工具类代码测试信息测试代码测试结果遇到的问题getContentLength()的滥用调用的错误慎用请求输出流flush()方法未写入标识调用错误总结前言 之前写的调用第三方接口&…

【机器学习】推荐系统

推荐系统的工作原理 推荐模型如何进行推荐将取决于您拥有的数据类型。如果您只拥有过去发生的交互数据,您可能有兴趣使用协作过滤。如果您有描述用户及其与之交互过的物品的数据(例如,用户的年龄、餐厅的菜系、电影的平均评价)&a…

Windows线程 信号量 CreateSemaphore创建信号量、RelaseSemaphore设置信号量

信号量 相关问题 类似于事件(作用类似),解决通知的相关问题。但提供一个计数器,可以设置次数。 信号量的使用 1.创建信号量 HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,//参数作废,基本用N…

临近期末,这些题不来看看吗?(下)

目录 1、打印1~100之间所有3的倍数(三种方法) 2、写出3给整数从大到小输出 3、给定两个数,求这两个数的最大公约数 4、 递归实现n的k次方 5、写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和 6、编写一个…

二叉树模板套题——相同的树的应用

文章目录力扣100. 相同的树递归展开图力扣572. 另一棵树的子树递归展开图力扣101. 对称二叉树递归展开图力扣100. 相同的树 给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同,并且节点具有相同的值&#xf…

四、nginx正向代理

一、正向代理 解释:正向代理指的是客户端通过访问目标服务端,再由目标服务端来转发流量访问互联网 结构图如下: 好处:这样做的好处是,当客户端通过服务端访问互联网某个网站时,该网站获得的IP地址是服务…

STEAM上的一款电路模拟神器 — CRUMB Circuit Simulator

摘要:这几天在逛steam商店时,发现了一款有意思的电路仿真软件CRUMB Circuit Simulator(CRUMB电路模拟器),觉得挺有意思的,就下载了玩了一下。 这款模拟电路软件的东西不多,基础的元器件都有&…

关于赚钱这件事,必须做到「金钱场」、「认知场」和「人脉场」三场统一

每周末,我会将我付费星球内的精华文章,在每周六或周日以付费文章的方式在公众号分享给大家,如果你不想加入我的星球,还想看的话,可以在这里付费看。当然,加入星球会更划算,因为星球内内容更多&a…