索引结构

概述

MySQL 的索引是在存储引擎层实现的,不同的存储引擎有不同的索引结构,主要包含以下几种:

索引结构描述
B+Tree索引最常见的索引类型,大部分引擎都支持 B+ 树索引
Hash索引底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询
R-tree(空间索引)空间索引是MyISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少
Full-text(全文引)

是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES

MySQL 中所支持的所有的索引结构,接下来,我们再来看看不同的存储引擎对于索引结构的支持情况。

索引InnoDBMyISAMMemory
B+tree索引支持支持支持
Hash 索引不支持不支持支持
R-tree 索引不支持支持不支持
Full-text5.6版本之后支持支持不支持

注意:我们平常所说的索引,如果没有特别指明,都是指B+树结构组织的索引。

具体实现

B-Tree与B+Tree

B-Tree

B-Tree,B树是一种多叉路衡查找树,相对于二叉树,B树每个节点可以有多个分支,即多叉。

以一颗最大度数(max-degree)为5(5阶)的b-tree为例,那这个B树每个节点最多存储4个key,5个指针:

B+Tree

B+Tree是B-Tree的变种,我们以一颗最大度数(max-degree)为4(4阶)的b+tree为例,来看一下其结构示意图:

我们可以看到,两部分:

  • 绿色框框起来的部分,是索引部分,仅仅起到索引数据的作用,不存储数据。

  • 红色框框起来的部分,是数据存储部分,在其叶子节点中要存储具体的数据。

B+Tree 与 B-Tree 的区别

最终我们看到,B+Tree 与 B-Tree 相比,主要有以下三点区别:

  • 所有的数据都会出现在叶子节点。

  • 叶子节点形成一个单向链表。

  • 非叶子节点仅仅起到索引数据作用,具体的数据都是在叶子节点存放的。

上述我们所看到的结构是标准的 B+Tree 的数据结构,接下来,我们再来看看 MySQL 中优化之后的 B+Tree。

MySQL 索引数据结构对经典的 B+Tree 进行了优化。在原 B+Tree 的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的 B+Tree,提高区间访问的性能,利于排序。

页(Page)的概念与作用

在关系型数据库(如 MySQL InnoDB、Oracle、SQL Server 等)中,最常用的索引结构是 B+ 树(或其变种)。B+ 树索引在磁盘或持久化存储上,都是以“页(page)”为最小 I/O 单元来管理的

  1. 页(Page)是什么?

    • 页(也称数据页、块 block)是数据库读写时的最小单位,典型大小为 4 KB、8 KB 或 16 KB。

    • 每个页在内存中对应一个缓冲区帧(buffer frame),从磁盘读入时,整个页一起加载;修改时,整个页也会被标记为“脏页”并迟缓写回。

  2. 为什么要用页?

    • I/O 单元磁盘和 OS 的 I/O 都是按页(或块)做的,读写整页比逐条读写要高效得多。

    • 缓存管理:数据库的 Buffer Pool 也是以页为单位进行加载和置换。

    • 空间管理:页作为固定大小的容器,便于分配、回收和查找空闲空间。

B+ 树的逻辑结构与页的映射

┌───────────┐┌──────▶│ Internal  │◀──────┐│       │  page(s)  │       ││       └───────────┘       │┌──┴──┐                    ┌───┴──┐│ ... │                    │ ...  │└──┬──┘                    └───┬──┘│       ┌───────────┐       │└──────▶│ Leaf page │◀──────┘└───────────┘
  1. 内部节点(Internal node)对应一个或多个页

    • 存放 键值 + 子节点指针(页号或内存指针)。

    • 用于路由查找:从根开始,根据键值范围逐层向下定位到叶子页。

  2. 叶子节点(Leaf node) 对应一系列连续页

    • 真正存放 完整的索引记录聚簇索引的全行数据

    • 通常包含:

      • 索引键(Key)

      • 若是非聚簇索引,则附带 主键 作为“行定位指针”;

      • 若是聚簇索引(Clustered Index),叶子页直接存放整行数据。

  3. 页之间的链表

    • 叶子页还会双向链成一个链表,方便范围扫描;

    • 内部节点页在分裂/合并时,也可能维护兄弟指针或在父节点更新。

页内记录的组织

  1. 页头(Header)

    • 存放页类型(内部/叶子)、当前记录数、Free Space 指针、链表指针(前驱/后继页号)等元信息。

  2. 记录目录(Slot Array)

    • 有些数据库(如 InnoDB)在页尾维护一个 Slot Array,存放每条记录在页内的偏移。

    • 插入/删除只需调整 Slot Array 及相应记录位置,避免大量移动。

  3. 记录存储(Record Storage)

    • 记录以物理或逻辑顺序(根据索引键)存储在页的主体区域。

    • 有的系统支持 前缀压缩:只存储键的增量部分,减少空间。

  4. 空闲空间管理(Free Space)

    • 页头维护一个指向空闲区(free space)的指针;新记录优先填满空闲区,再触发分裂。

页分裂与合并

页分裂(Page Split)
  • 触发:当插入一条记录到已无足够空闲空间的叶子页或内部页时。

  • 过程

    1. 分配一个“同级”新页;

    2. 将原页中大约一半偏后的记录(或指针)移动到新页;

    3. 在父节点中插入一个新的键和指向新页的指针;若父页也满,则递归向上分裂。

  • 影响

    • 写放大:要写两个页(原页&新页)及更新父页;

    • 碎片化:原本连续的逻辑键可能跨两个页,影响范围扫描的 I/O 连续性;

    • 内存/缓存抖动:新页要加载到内存,可能驱逐其他页面。

页合并(Page Merge)
  • 触发:当删除操作导致某页的记录数低于某个阈值(例如空闲空间过大),并且相邻页也较空时。

  • 过程:把两个兄弟页的记录合并到一页,释放一个页号,并相应在父节点删除指针;若父节点太空,也可递归向上合并。


顺序 vs. 随机主键对页分裂的影响

  • 顺序主键(自增、时间戳)

    • 新记录总插入到叶子页的最右端,

    • 只会在最右页“尾部”分裂;

    • 降低对中间页的频繁分裂,保证大部分页都被顺序填满。

  • 随机/无序主键(UUID、散列)

    • 每次插入可以分散到任何叶子页,

    • 导致各页随机“爆满”并分裂,

    • 频繁触发分裂,带来更高的写放大和碎片率。

索引分类

索引分类

在MySQL数据库,将索引的具体类型主要分为以下几类:主键索引、唯一索引、常规索引、全文索引。

分类含义特点关键字
主键索引针对表中主键创建的索引默认自动创建,只能有一个PRIMARY
唯一索引避免同一个表中某数据列中的值重复可以有多个UNIQUE
常规索引快速定位特定数据可以有多个
全文索引全文索引查找的是文本中的关键词,而不是比较索引中的值可以有多个FULLTEXT

聚集索引 & 二级索引

而在 InnoDB 存储引擎中,根据索引的存储形式,又可以分为以下两种:

分类含义特点
聚集索引 (Clustered Index)将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据必须有,而且只有一个
二级索引 (Secondary Index)将数据与索引分开存储,索引结构的叶子节点关联的是对应的主键可以存在多个

聚集索引选取规则:

  • 如果存在主键,主键索引就是聚集索引。

  • 如果不存在主键,将使用第一个唯一 (UNIQUE) 索引作为聚集索引。

  • 如果表没有主键,或没有合适的唯一索引,则 InnoDB 会自动生成一个 rowid 作为隐藏的聚集索引。

查找过程-回表查询

接下来,我们来分析一下,当我们执行如下的SQL语句时,具体的查找过程是什么样子的

具体过程如下:

①. 由于是根据name字段进行查询,所以先根据name='Arm'到name字段的二级索引中进行匹配查找。但是在二级索引中只能查找到Arm对应的主键值10。

②. 由于查询返回的数据是*,所以此时,还需要根据主键值10,到聚集索引中查找10对应的记录,最终找到10对应的行row。

③. 最终拿到这一行的数据,直接返回即可。

这个过程也称为回表查询

回表查询: 这种先到二级索引中查找数据,找到主键值,然后再到聚集索引中根据主键值,获取

数据的方式,就称之为回表查询。

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

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

相关文章

(纯新手教程)HTML零基础教学

(下一章:python网络爬虫)HTML 简介HTML(HyperText Markup Language,超文本标记语言)是用于创建网页的标准标记语言。什么是 HTML?HTML 不是编程语言,而是一种标记语言使用标签来描述…

前端面试宝典---项目难点2-智能问答对话框采用虚拟列表动态渲染可视区域元素(10万+条数据)

引言 在我参与智能问答项目中一个智能体回话并不会像豆包一样,每次新建会话都是是从头开始,而项目中你想创建新会话就像chatbox一样,是点击橡皮擦开启新的聊天上下文,但是直接的聊天记录依然存在,针对超过十万&#xf…

Python元组:不可变数据的强大用法

文章目录元组概念1.基本特性2.创建元组3.访问元素4.元组的不可变性5.元组操作6.元组解包7.命名元组8.元组与列表的比较9.元组的优势10.适用场景11.常用方法小结元组 概念 元组是 Python 中一个非常重要的内置数据结构,它与列表(list)相似但具有关键差异。下面我将…

若尔盖湿地的花湖

花湖位于若尔盖县和甘肃的郎木寺之间的213国道旁,属于若尔盖湿地国家级自然保护区内。又名“梅朵湖”,因阳光照射下湖面色彩斑斓如绚丽的花瓣得名。花湖的大门是梯形高大石柱搭成,我们需要过天桥到对面检票坐小交通。通过车窗看到一层一层的云…

50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleClickHeart(双击爱心)

&#x1f4c5; 我们继续 50 个小项目挑战&#xff01;—— DoubleClickHeart组件 仓库地址&#xff1a;https://github.com/SunACong/50-vue-projects 项目预览地址&#xff1a;https://50-vue-projects.vercel.app/ 使用 Vue 3 的 Composition API&#xff08;<script se…

1-绪论-1-数据结构的基本概念

&#x1f389; 数据结构的魔法世界&#x1f4da;&#x1f468;‍&#x1f393;“数据就像大海中的浪花&#xff0c;结构则是那神秘的洋流。掌握数据结构&#xff0c;就是掌握在信息海洋中自由航行的力量&#xff01;”引言&#xff1a;为什么要学数据结构&#xff1f;&#x1f…

linux网络相关命令简介

目录 一、IP命令 1、Link或L:管理网络接口(网卡) 2、Address或Addr,A:管理Ip地址 3、Route或R:管理路由表

教育培训机构如何为课程视频添加防盗录的强水印?

在知识付费时代&#xff0c;教育培训机构的课程视频是核心资产&#xff0c;但盗录、非法传播等问题却让机构防不胜防。如何在不影响学员观看体验的前提下&#xff0c;为课程视频添加“强效防盗水印”&#xff0c;精准追踪泄露源头&#xff1f;本文将为您揭秘高安全性水印的添加…

python的形成性考核管理系统

前端开发框架:vue.js 数据库 mysql 版本不限 后端语言框架支持&#xff1a; 1 java(SSM/springboot)-idea/eclipse 2.NodejsVue.js -vscode 3.python(flask/django)–pycharm/vscode 4.php(thinkphp/laravel)-hbuilderx 数据库工具&#xff1a;Navicat/SQLyog等都可以 摘要 随着…

A*算法详解

A*算法详解一、A*算法基础概念1.1 算法定位1.2 核心评估函数1.3 关键数据结构二、A*算法的核心步骤三、启发函数设计3.1 网格地图中的启发函数3.2 启发函数的选择原则三、Java代码实现四、启发函数的设计与优化4.1 启发函数的可采纳性4.2 启发函数的效率影响4.3 常见启发函数对…

.net winfrom 获取上传的Excel文件 单元格的背景色

需求&#xff1a;根据Excel某行标注了黄色高亮颜色&#xff0c;说明该行数据已被用户选中(Excel文件中并没有“已选中”这一列&#xff0c;纯粹用颜色表示)&#xff0c;导入数据到数据库时标注此行已选中直接上代码&#xff1a;//选择Excel文件private void btnBrowse_Click(ob…

OpenAI GPT-4o技术详解:全能多模态模型的架构革新与生态影响

本文由「大千AI助手」原创发布&#xff0c;专注用真话讲AI&#xff0c;回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我&#xff0c;一起撕掉过度包装&#xff0c;学习真实的AI技术&#xff01; ⚙️ 一、核心定义与发布背景 官方定位 GPT-4o&#xff08;“o”代表“…

⚡ 构建真正的高性能即时通讯服务:基于 Netty 集群的架构设计与实现

引子 在前面的文章中&#xff0c;我们基于 Netty 构建了一套单体架构的即时通讯服务。虽然单体架构在开发初期简单高效&#xff0c;但随着用户量的增长和业务规模的扩大&#xff0c;其局限性逐渐显现。当面对高并发场景时&#xff0c;单体 Netty 服务很容易触及性能天花板&…

原来时间序列挖掘这么简单

先搞懂&#xff1a;啥是时间序列&#xff1f;简单说&#xff0c;时间序列就是按时间顺序记下来的数据。比如&#xff1a;你每天早上 8 点测的体重&#xff0c;连起来就是 “体重时间序列”&#xff1b;超市每天的销售额&#xff0c;连起来就是 “销售时间序列”&#xff1b;城市…

基于Python的豆瓣图书数据分析与可视化系统【自动采集、海量数据集、多维度分析、机器学习】

文章目录有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍每文一语有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主 项目介绍 豆瓣图书数据智能分析系统是一个集数据采集、清洗、分析与可视化于一体的综合性项…

2.3 数组与字符串

学习目标&#xff1a; 理解数组和字符串的概念&#xff08;存储多个数据的“盒子”&#xff09;。掌握数组的声明、初始化和遍历方法。能用字符串处理简单文本问题&#xff08;如字符计数、回文判断&#xff09;。1 一维数组 基本概念 比喻&#xff1a; 数组就像“储物柜”&…

C# 网口demo

bool _testStatus false; private void btnOpsStart_Click(object sender, EventArgs e) {int delay Convert.ToInt32(txtdelay.Text.Trim());txtView.Clear();txtView.AppendText("******************************************开始烤机*******************************…

MATLAB 安装 ACADO 的完整步骤

✅ MATLAB 安装 ACADO 的完整步骤 &#x1f4e6; 一、准备工作 1. 下载 ACADO Toolkit 官方地址&#xff1a;https://github.com/acado/acado 2. 解压 ACADO 到你指定的路径&#xff0c;例如&#xff1a; D:\user\acado-master建议路径中 不要包含中文或空格。 &#x1f9f…

[逆向工程]160个CrackMe入门实战之Afkayas.1.Exe解析(二)

[逆向工程]160个CrackMe入门实战之Afkayas.1.Exe解析&#xff08;二&#xff09; 一、前言 在逆向工程的学习路径上&#xff0c;CrackMe程序是初学者最好的练手材料。今天我们要分析的是160个CrackMe系列的第二题——Afkayas.1.Exe。这个程序由Afkayas编写&#xff0c;难度为★…

本地电脑安装Dify|内网穿透到公网

1.安装Docker Docker: Accelerated Container Application Development 2.添加 PATH 3.安装Dify https://github.com/langgenius/dify.git 把.env.example文件名改为.env 4.更换镜像源 {"builder": {"gc": {"defaultKeepStorage": "20G…