什么是 MySQL 的“回表”?

news2024/9/27 7:18:02

1. 索引结构

要搞明白这个问题,需要大家首先明白 MySQL 中索引存储的数据结构。这个其实很多小伙伴可能也都听说过,B+Tree 嘛!

B+Tree 是什么?那你得先明白什么是 B-Tree,来看如下一张图:

前面是 B-Tree,后面是 B+Tree,两者的区别在于:

  • B-Tree 中,所有节点都会带有指向具体记录的指针;B+Tree 中只有叶子结点会带有指向具体记录的指针。

  • B-Tree 中不同的叶子之间没有连在一起;B+Tree 中所有的叶子结点通过指针连接在一起。

  • B-Tree 中可能在非叶子结点就拿到了指向具体记录的指针,搜索效率不稳定;B+Tree 中,一定要到叶子结点中才可以获取到具体记录的指针,搜索效率稳定。

基于上面两点分析,我们可以得出如下结论:

  • B+Tree 中,由于非叶子结点不带有指向具体记录的指针,所以非叶子结点中可以存储更多的索引项,这样就可以有效降低树的高度,进而提高搜索的效率。

  • B+Tree 中,叶子结点通过指针连接在一起,这样如果有范围扫描的需求,那么实现起来将非常容易,而对于 B-Tree,范围扫描则需要不停的在叶子结点和非叶子结点之间移动。

对于第一点,一个 B+Tree 可以存多少条数据呢?以主键索引的 B+Tree 为例(二级索引存储数据量的计算原理类似,但是叶子节点和非叶子节点上存储的数据格式略有差异),我们可以简单算一下。

计算机在存储数据的时候,最小存储单元是扇区,一个扇区的大小是 512 字节,而文件系统(例如 XFS/EXT4)最小单元是块,一个块的大小是 4KB。InnoDB 引擎存储数据的时候,是以页为单位的,每个数据页的大小默认是 16KB,即四个块。

基于这样的知识储备,我们可以大致算一下一个 B+Tree 能存多少数据。

假设数据库中一条记录是 1KB,那么一个页就可以存 16 条数据(叶子结点);对于非叶子结点存储的则是主键值+指针,在 InnoDB 中,一个指针的大小是 6 个字节,假设我们的主键是 bigint ,那么主键占 8 个字节,当然还有其他一些头信息也会占用字节我们这里就不考虑了,我们大概算一下,小伙伴们心里有数即可:

16*1024/(8+6)=1170

即一个非叶子结点可以指向 1170 个页,那么一个三层的 B+Tree 可以存储的数据量为:

1170*1170*16=21902400

可以存储 2100万 条数据。

在 InnoDB 存储引擎中,B+Tree 的高度一般为 2-4 层,这就可以满足千万级的数据的存储,查找数据的时候,一次页的查找代表一次 IO,那我们通过主键索引查询的时候,其实最多只需要 2-4 次 IO 操作就可以了。

大家先搞明白这个 B+Tree。

2. 两类索引

大家知道,MySQL 中的索引有很多中不同的分类方式,可以按照数据结构分,可以按照逻辑角度分,也可以按照物理存储分,其中,按照物理存储方式,可以分为聚簇索引和非聚簇索引。

我们日常所说的主键索引,其实就是聚簇索引(Clustered Index);主键索引之外,其他的都称之为非主键索引,非主键索引也被称为二级索引(Secondary Index),或者叫作辅助索引。

对于主键索引和非主键索引,使用的数据结构都是 B+Tree,唯一的区别在于叶子结点中存储的内容不同:

  • 主键索引的叶子结点存储的是一行完整的数据。

  • 非主键索引的叶子结点存储的则是主键值。

这就是两者最大的区别。

所以,当我们需要查询的时候:

  • 如果是通过主键索引来查询数据,例如 select * from user where id=100,那么此时只需要搜索主键索引的 B+Tree 就可以找到数据。

  • 如果是通过非主键索引来查询数据,例如 select * from user where username='javaboy',那么此时需要先搜索 username 这一列索引的 B+Tree,搜索完成后得到主键的值,然后再去搜索主键索引的 B+Tree,就可以获取到一行完整的数据。

对于第二种查询方式而言,一共搜索了两棵 B+Tree,第一次搜索 B+Tree 拿到主键值后再去搜索主键索引的 B+Tree,这个过程就是所谓的回表。

从上面的分析中我们也能看出,通过非主键索引查询要扫描两棵 B+Tree,而通过主键索引查询只需要扫描一棵 B+Tree,所以如果条件允许,还是建议在查询中优先选择通过主键索引进行搜索。

3. 一定会回表吗?

那么不用主键索引就一定需要回表吗?

不一定!

如果查询的列本身就存在于索引中,那么即使使用二级索引,一样也是不需要回表的。

举个例子,我有如下一张表:

uname 和 address 字段组成了一个复合索引,那么此时,虽然这是一个二级索引,但是索引树的叶子节点中除了保存主键值,也保存了 address 的值。

我们来看如下分析:

可以看到,此时使用到了 uname 索引,但是最后的 Extra 的值为Using index,这就表示用到了索引覆盖扫描(覆盖索引),此时直接从索引中过滤不需要的记录并返回命中的结果,这一步是在 MySQL 服务器层完成的,并且不需要回表。

4. 扩展

基于第一、二小节的分析,我们再来捋一捋为什么在数据库中建议使用自增主键。

  • 自增主键往往占用空间比较小,int 占 4 个字节,bigint 占 8 个字节。由于二级索引的叶子节点存储的就是主键,所以如果主键占用空间小,意味着二级索引的叶子节点将来占用的空间小(间接降低 B+Tree 的高度,提高搜索效率)。

  • 自增主键插入的时候比较快,直接插入即可,不会涉及到叶子节点分裂等问题(不需要挪动其他记录);而其他非自增主键插入的时候,可能要插入到两个已有的数据中间,就有可能导致叶子节点分裂等问题,插入效率低(要挪动其他记录)。

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

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

相关文章

不止稳定快速,看华为云CDN如何在国际云服务市场中“分蛋糕”

互联网时代,网络的应用已十分普及,但依然存在下载慢、网络卡顿的现象。如企业业务运行过程中出现的卡顿现象导致数据延时;各校因疫情等原因网课时间长、访问应用人数过多,造成网络卡顿现象严重,无法带来良好的上课体验…

ArcGIS基础实验操作100例--实验16对字段自定义赋值

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台:ArcGIS 10.6 实验数据:请访问实验1(传送门) 基础编辑篇--实验16 对字段自定义赋值 目录 一、实验背景 二、实验数据 三、实验步骤 (1…

玩转云服务器,怎样用云服务器架设搭建游戏:浪剑天下架设教程,手把手教你架设游戏服务器,小白一看就会

服务器详情:服务器系统:LINUX-CENTOS7.6服务器配置:2核4G以上配置 搭建教程: 第一步:安装宝塔: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh &…

Allegro如何输出IPC文件操作指导

Allegro如何输出IPC文件操作指导 IPC文件是PCB上所有网络连接关系文件,在PCB生产前网表比对必须的文件,如下图 如何输出IPC文件,具体操作如下 选择File选择IPC356

磁实验比较-反激式变压器(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

代码随想录拓展day5 129. 求根节点到叶节点数字之和;1382.将二叉搜索树变平衡;100. 相同的树;116. 填充每个节点的下一个右侧节点指针

代码随想录拓展day5 129. 求根节点到叶节点数字之和;1382.将二叉搜索树变平衡;100. 相同的树;116. 填充每个节点的下一个右侧节点指针 全部都是关于二叉树的题目,对二叉树的遍历方式又是一个复习。 129. 求根节点到叶节点数字之…

Java 访问权限控制

使用访问权限控制的原因: 使用户不要触碰到那些不该触碰的部分类库设计者可以更改类的内部工作模式,而不必担心整体程序造成影响 访问权限修饰词 Java具有三种访问权限修饰词(public private protected),划分出了四种访问权限(public prot…

WeakHashMap引起内存溢出,线程数剧增

1.问题背景 代码通过jarLoader的方式,实现了一个数据库多个客户端版本兼容的情况,一个客户端使用一个jarLoader,实现jar的隔离。 同时,jarLoader使用weekhashmap做缓存。 hive做批量查询表的元数据时,引入了线程池。…

NodeJS学习笔记一

文章目录1. 模块化1.1 模块作用域2. 内置API模块3. 自定义模块3.1 向外共享模块作用域中的成员3.2 使用误区3.3 CommonJS模块化规范4. 第三方API模块4.1 npm包管理目录4.2 包管理配置文件 package.json4.3 devDependencies节点4.4 切换npm的包镜像源4.5 包的分类4.5.1 项目包4.…

【cfeng-Work】work项目理解

work 项目 内容管理入职项目环境搭建商用项目 和 学习项目经验分享easily 分享work 见解 学习项目(非商用)相比工作中的商用项目差别还是很大的… Cfeng 最近开始工作, 接下来我将分享一下对于学校中的project环境和 work环境的相关理解 入职…

生成式对抗网络(GAN)原理推导与网络构建思路

0 引言 设想这样的场景:你是一个工作室的老板,你的工作室主要用来生产名画的赝品;而真正的名画则为前人所创造,存放在收藏室中。你的赝品画会和真品画一起被鉴定家鉴定,而你的终极目标是成为一个以假乱真的工艺大师。…

设置 Postman 环境并调用 API

云开发自带 API 调试 功能,可快速进行 API 接口调试,同时也支持通过 Postman 调用 API 获取设备信息或控制设备。本文介绍如何设置调用云开发 API 的 Postman 开发环境及调用接口实践。 配置环境 安装 Postman 8.2.2 及以上版本桌面软件。 版本过低会出…

Python类中的__init__() 和 self 的解析

1、Python中self的含义 self,英文单词意思很明显,表示自己,本身。 此处有几种潜在含义: 1.这里的自己,指的是,实例Instance本身。 2.同时, 由于说到“自己”这个词,都是和相对而…

《计算机网络》——第七章知识点

防火墙:特殊编程的路由器,实施访问控制策略。分为网络级防火墙(防止网络出现非法入侵)和应用级防火墙(进行应用的访问控制)。 本次文章详细PDF请点击以下链接查看: https://download.csdn.net/download/qq_53142796/87353770https://download.csdn.n…

市场回暖进行时,实体店商户们千万不要做这三件事!

随着防控措施的进一步优化,市场环境逐渐复苏,许多商户都趁着这段时间开始着手做准备,想要趁年前赚到消费回暖的第一波红利。 但是方向一旦错了,不管付出的努力有多少,最终也只能和想要的结果背道而驰;为了避…

图文结合带你搞懂MySQL日志之Slow Query Log(慢查询日志)

GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:KAiTO文章来源:GreatSQL社区原创 什么是慢查询日志 MySQL 的慢查询日志,用来记录在 M…

ORB-SLAM2 --- Tracking::Track 追踪线程解析

1.函数作用 ORB-SLAM2的三大线程之一---跟踪线程,负责估计运动信息、跟踪局部地图。 追踪线程的主要工作原理就是我们从数据集中读入一帧帧,刚开始的时候跟踪线程没有进行初始化(没有初始化不知道世界坐标系的原点和相机的位姿)&a…

做开发的朋友说软件测试是个人都能学,我当面怒怼

那就分析一下测试工程师需要会哪些技能: 01 软件测试理论 作为一个软件测试人员,总不能不知道软件测试本身的东西吧。 你总要知道软件测试是什么?什么是测试用例?什么是缺陷?软件测试有些什么特点?这些…

OpenHarmony#深入浅出学习eTs#(八)“猜大小”小游戏

本项目Gitee仓地址:[深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com)]( 上一章节提到的模拟器存在的BUG问题,目前没有办法直接改善,本来打算直接使用鸿蒙远程设备来实现,但是发现支持API8的设备都被抢光了(包括模…

如何使用谷歌地图和LightningChart创建地理空间地图图表?

LightningChart JS 是一款高性能的 JavaScript 图表工具,专注于性能密集型、实时可视化图表解决方案。 LightningChart .JS | 下载试用(qun:740060302)https://www.evget.com/product/4189/download Google Static Maps API 是一…