当前位置: 首页 > article >正文

B+树知识点总结

核心目标:减少磁盘 I/O

数据库系统(如 MySQL)的主要性能瓶颈通常在于磁盘 I/O(读取和写入数据到物理硬盘的速度远慢于内存访问)。B+ 树的设计核心就是最大限度地减少访问数据时所需的磁盘 I/O 次数

一、B+ 树的基本结构回顾

在深入存储之前,先快速回顾 B+ 树的关键特性:

  1. 多路平衡搜索树: 每个节点可以有多个子节点(远多于二叉树的 2 个),并且树始终保持平衡(所有叶子节点位于同一层)。
  2. 分层结构:
    • 根节点 (Root Node): 树的顶端。
    • 内部节点/非叶子节点 (Internal/Non-Leaf Nodes): 位于根节点和叶子节点之间。它们只存储索引键 (Key) 和指向其子节点(可以是内部节点或叶子节点)的指针 (Pointer)
    • 叶子节点 (Leaf Nodes): 树的底层。它们存储索引键 (Key) 以及与该键关联的实际数据或指向实际数据的指针。在 MySQL InnoDB 中,对于主键索引(聚簇索引),叶子节点直接存储数据行;对于二级索引,叶子节点存储索引列的值和对应的主键值。
  3. 节点填充度高: 节点通常会被填充到一定程度(例如 50% 或更多),以优化存储利用率和减少树的高度。
  4. 叶子节点链表: 所有叶子节点通过双向指针(前驱和后继指针)按顺序连接成一个有序链表。这使得范围查询 (WHERE col BETWEEN X AND Y) 变得极其高效,只需定位到起始键所在的叶子节点,然后沿着链表顺序扫描即可,无需回溯到上层节点。
  5. 所有数据在叶子层: 这是 B+ 树与 B 树的关键区别。非叶子节点不存储实际数据记录,只存储用于导航的键值。实际数据(或指向数据的指针)只存在于叶子节点。这使得非叶子节点可以存储更多的键值,从而显著降低树的高度。

二、B+ 树如何映射到硬盘存储(以 InnoDB 为例)

MySQL InnoDB 存储引擎是使用 B+ 树作为其索引结构的典型代表。硬盘存储的核心单位是 页 (Page)

  1. 存储的基本单位:页 (Page)

    • InnoDB 中,磁盘和内存之间数据传输的最小单位是
    • 默认页大小通常是 16KB (可以通过 innodb_page_size 配置,但 16KB 是最常见和推荐的)。
    • B+ 树的每个节点(根节点、内部节点、叶子节点)在物理存储上都对应一个或多个这样的 16KB 页。 大多数情况下,一个节点就存储在一个页里。非常大型的节点(比如叶子节点包含大量行)可能需要多个页存储,但 InnoDB 的设计通常尽量避免这种情况,通过分裂机制维持一个节点对应一个页。
  2. 页的内部结构
    一个 InnoDB 页(16KB)内部包含多个部分,用于高效存储和管理数据:

    • 页头 (Page Header): 存储页的元信息,如页类型(叶子页?非叶子页?)、页号、前后页指针(用于叶子节点链表或文件段内的链接)、页内记录数、槽信息(Slots)的位置等。
    • Infimum + Supremum Records: 两个系统生成的伪记录,分别表示页内“最小”和“最大”记录,用于界定边界。
    • 用户记录 (User Records): 这是页的核心区域,存储实际的行记录(在叶子节点)或索引条目(在非叶子节点)。
      • 叶子节点页: 存储的是 索引键值 + 完整数据行(对于聚簇索引)索引键值 + 主键值(对于二级索引)。记录按主键(聚簇索引)或索引键(二级索引)顺序物理存储(逻辑上连续,物理上可能因插入/删除而碎片化)。
      • 非叶子节点页: 存储的是 索引键值 + 指向子节点页的指针(页号)。这些键值是其子节点中键值范围的“分隔符”。例如,一个键值 K 对应的指针指向的页包含所有键值 <= K 的记录(具体规则取决于实现,但思想类似)。
    • 页目录 (Page Directory): 这是 InnoDB 在页内实现的小型索引结构,通常位于页尾部。它包含一个槽 (Slot) 数组。每个槽指向页内用户记录区域中的某些记录的位置(通常是每隔几行设一个槽)。槽内的记录是按主键(或索引键)排序的。页目录的作用是加速页内记录的查找。当在页内查找一条记录时,先通过二分查找在页目录中找到记录所在的槽(大致范围),然后再在槽指向的少量记录中进行顺序查找。这避免了在页内进行全表扫描。
    • 页尾 (Page Trailer): 包含校验和 (Checksum) 信息,用于检测页在写入磁盘或从磁盘读取时是否发生损坏。
  3. B+ 树在硬盘上的组织

    • 整个 B+ 树索引存储在 .ibd 表空间文件中(对于独立表空间)或共享的 ibdata 文件中(对于系统表空间)。
    • 根节点页: 固定存储在某个特定位置(例如,数据字典中会记录每个索引的根页号)。
    • 节点关系: 非叶子节点页中的“指针”字段存储的是其子节点页的页号 (Page Number)。这个页号就是在表空间文件中的逻辑偏移量(或物理地址映射)。
    • 叶子节点链表: 叶子节点页的页头中存储了前一个页号 (Previous Page Number)后一个页号 (Next Page Number),从而将所有的叶子节点串联成一个有序的双向链表。这个链表是按索引键值排序的。
    • 数据文件即索引文件 (聚簇索引): 对于 InnoDB 的主键索引(聚簇索引),叶子节点包含了完整的行数据。这意味着数据行本身就按照主键顺序存储在 B+ 树的叶子节点页中。因此,InnoDB 的表数据文件(.ibd)本身就是按主键组织的巨大 B+ 树索引文件。
    • 二级索引: 二级索引也是 B+ 树结构,但它的叶子节点存储的是索引列的值 + 对应的主键值。当通过二级索引查找数据时,引擎先在二级索引 B+ 树中找到目标记录的主键值,然后回表 (Bookmark Lookup) 到主键索引(聚簇索引)的 B+ 树中查找完整的行数据。二级索引的叶子节点之间也通过双向链表连接。

三、索引数据如何工作(查询过程示例)

假设我们有一个 users 表,主键是 id,并在 age 列上建立了一个二级索引。我们执行查询 SELECT * FROM users WHERE age = 30;

  1. 定位索引根: MySQL 知道查询条件在 age 索引上。它从数据字典中找到 age 索引的 B+ 树根节点所在的页号。
  2. 加载根页: 从硬盘读取该根页到内存缓冲区池 (Buffer Pool)。
  3. 遍历非叶子节点:
    • 在根页(非叶子节点)中,使用二分查找(利用页目录加速页内查找)找到第一个大于或等于 30 的键值 K。找到 K 前面那个指针指向的子节点页 P1
    • 从硬盘加载页 P1(如果不在 Buffer Pool 中)到内存。
    • 在页 P1(可能是另一个非叶子节点或叶子节点)中,同样用二分查找定位到键值 30 可能存在的子节点页 P2
    • 重复这个过程,沿着树向下,直到定位到包含键值 30(或 30 应该存在的范围)的叶子节点页 P_leaf。由于 B+ 树是平衡的,这个过程通常只需要 3-4 次 I/O(取决于数据量大小和树的高度)。
  4. 在叶子节点页查找:
    • 加载叶子节点页 P_leaf 到内存(如果不在)。
    • P_leaf 页内,利用页目录 (Page Directory) 进行二分查找,快速定位到包含 age=30 的记录的位置。
    • 由于二级索引叶子节点存储的是 (age, id),此时引擎找到了所有 age=30 的记录的 id 值列表。
  5. 回表 (对于二级索引):
    • 对于找到的每一个 id 值,引擎需要获取完整的行数据。
    • 引擎转向主键索引(聚簇索引) 的 B+ 树。
    • 使用相同的 B+ 树查找过程(定位根->遍历非叶子节点->定位叶子节点),根据 id 值在主键索引的叶子节点中找到对应的完整数据行
    • 每次根据一个 id 回表查找,理论上都可能产生一次 I/O(如果目标页不在 Buffer Pool 中)。如果 age=30 的记录很多,这可能导致大量的随机 I/O。这就是为什么覆盖索引(索引包含所有查询列)能显著提升性能的原因,因为它避免了回表。
  6. 范围查询: 如果查询是 WHERE age BETWEEN 25 AND 35
    • age 索引 B+ 树中找到 age=25 所在的叶子页 P_start
    • 加载 P_start,读取所有 age>=25 的记录(直到该页结束)。
    • 利用叶子节点的双向链表指针,加载下一个叶子页 P_next,继续读取记录,直到遇到 age > 35 的记录为止。范围查询利用链表顺序扫描,效率很高。

四、B+ 树相对于其他结构(如哈希、B 树)的优势

  1. 极低的树高度: 多路分支特性使得即使存储海量数据(亿级、十亿级),树的高度通常也只有 3-4 层。查找任何记录最多只需要 3-4 次磁盘 I/O。
  2. 高效的磁盘 I/O:
    • 节点大小(页大小 16KB)与磁盘块大小(通常 4KB)对齐或成倍数关系,一次 I/O 能读取大量有用信息。
    • 顺序预读:磁盘顺序读取远快于随机读取。B+ 树的局部性原理(相邻节点/记录物理位置较近)和叶子节点链表使得范围扫描和全表扫描可以利用磁盘预读特性,大幅提升 I/O 效率。
  3. 出色的范围查询: 叶子节点链表使得范围查询 (BETWEEN, >, <, LIKE 'prefix%') 非常高效,只需定位到起点,然后顺序扫描链表即可。
  4. 稳定的查询性能: 所有查询路径长度相同(树平衡),查找任何记录所需 I/O 次数基本相同,性能可预测。
  5. 高效的插入和删除 (相对): 虽然插入/删除可能导致节点分裂或合并,但操作仍然集中在局部的少数节点上(通常是叶子节点及其父节点),影响范围有限。分裂/合并逻辑也相对高效。

五、总结

MySQL(特别是 InnoDB)使用 B+ 树作为其核心索引结构,通过以下机制高效地在硬盘上存储和索引数据:

  1. 页式存储: 以 16KB 页为基本单位在硬盘上组织 B+ 树的节点(根、内部、叶子)。
  2. 节点映射: 每个 B+ 树节点通常对应一个物理页。非叶子节点存储键和子页指针;叶子节点存储键和数据(聚簇索引)或键和主键(二级索引)。
  3. 页内优化: 页内使用 页目录 (Slots) 实现快速二分查找,避免页内全扫描。
  4. 叶子链表: 叶子节点通过双向链表串联,实现高效的范围扫描。
  5. 聚簇索引: 主键索引的叶子节点包含完整数据行,数据文件即索引文件。
  6. 二级索引与回表: 二级索引叶子节点存储主键值,查询完整数据需回表到主键索引。
  7. 减少 I/O: 设计核心在于利用 B+ 树矮胖、多分支、顺序访问的特性,以及页大小与磁盘 I/O 的匹配,最大限度地减少昂贵的磁盘随机 I/O 次数。

理解 B+ 树在硬盘上的存储和工作原理,是理解数据库性能调优(如索引设计、覆盖索引、避免回表、利用顺序 I/O)的基础。它解释了为什么某些查询快,某些查询慢,以及如何通过合理的索引策略来优化数据库访问。

相关文章:

B+树知识点总结

核心目标&#xff1a;减少磁盘 I/O 数据库系统&#xff08;如 MySQL&#xff09;的主要性能瓶颈通常在于磁盘 I/O&#xff08;读取和写入数据到物理硬盘的速度远慢于内存访问&#xff09;。B 树的设计核心就是最大限度地减少访问数据时所需的磁盘 I/O 次数。 一、B 树的基本结…...

Halcon透视矩阵

在 Halcon中&#xff0c;透视变换矩阵用于将图像从一个视角转换到另一个视角&#xff0c;常用于图像校正和几何变换。以下是计算透视变换矩阵的步骤及代码示例。 透视形变图像校正的步骤 对图像左简单的处理&#xff0c;分割要校正的区域&#xff1b;提取区域的顶点坐标信息&…...

SpringCloud——OpenFeign

概述&#xff1a; OpenFeign是基于Spring的声明式调用的HTTP客户端&#xff0c;大大简化了编写Web服务客户端的过程&#xff0c;用于快速构建http请求调用其他服务模块。同时也是spring cloud默认选择的服务通信工具。 使用方法&#xff1a; RestTemplate手动构建: // 带查询…...

007-nlohmann/json 项目应用-C++开源库108杰

本课为 fswatch&#xff08;第一“杰”&#xff09;的示例项目加上对配置文件读取的支持&#xff0c;同时借助 第三“杰” CLI11 的支持&#xff0c;完美实现命令行参数与配置文件的逻辑统一。 012-nlohmann/json-4-项目应用 项目基于原有的 CMake 项目 HelloFSWatch 修改。 C…...

移动端测试岗位高频面试题及解析

文章目录 一、基础概念二、自动化测试三、性能测试四、专项测试五、安全与稳定性六、高级场景七、实战难题八、其他面题 一、基础概念 移动端测试与Web测试的核心区别&#xff1f; 解析&#xff1a;网络波动&#xff08;弱网测试&#xff09;、设备碎片化&#xff08;机型适配&…...

gvim比较两个文件不同并合并差异

使用 gvim 比较两个文件的不同&#xff1a; 方式一&#xff0c;使用 gvim 同时打开两个待比较的文件。 比较通用方式是采用 gvim -d 选项&#xff0c;具体命令&#xff0c;如下&#xff1a; gvim -d <file1> <file2>方式二&#xff0c;先用 gvim 打开一个文件&am…...

App使用webview套壳引入h5(二)—— app内访问h5,顶部被手机顶部菜单遮挡问题,保留顶部安全距离

引入webview的页面添加safeAreaInsets&#xff0c;对weview的webviewStyles做处理 在myApp中改造 entry.vue代码如下 template><view class"entry-page" :style"{ paddingTop: safeAreaInsets.top px }"><web-view :webview-styles"we…...

Git GitHub Gitee

一、Git 是一个免费、开源的分布式版本控制系统。 版本控制&#xff1a;一种记录文件内容变化&#xff0c;以便将来查阅特定版本修订情况的系统。它最重要的就是可以记录文件修改历史记录&#xff0c;从而让用户可以看历史版本&#xff0c;方便版本切换。 1.和集中式版本控制…...

《深度体验 Egg.js:打造企业级 Node.js 应用的全景指南》

&#x1f680; 核心亮点&#xff1a;Koa 的二次觉醒 企业级基因&#xff1a;阿里多年双十一验证的框架稳定性插件化架构&#xff1a;config.plugins 实现功能模块即插即用渐进式演进&#xff1a;从 50 行代码到 5 万行代码的无缝扩容能力 &#x1f527; 实战配置解析&#xff…...

蓝桥杯2118 排列字母

问题描述 小蓝要把一个字符串中的字母按其在字母表中的顺序排列。 例如&#xff0c;LANQIAO 排列后为 AAILNOQ。 又如&#xff0c;GOODGOODSTUDYDAYDAYUP 排列后为 AADDDDDGGOOOOPSTUUYYY。 请问对于以下字符串&#xff0c;排列之后字符串是什么&#xff1f; WHERETHEREIS…...

Python应用break初解

大家好!作为 Python 初学者&#xff0c;控制循环的执行是编程中的基础技能之一。在本文中&#xff0c;我们将深入探讨break语句的用途和用法&#xff0c;帮助您更好地理解和掌握这一强大的工具。 定义: break是 Python 中的一个保留关键字&#xff0c;用于在循环中提前终止循环…...

PLSQLDeveloper配置OracleInstantClient连接Oracle数据库

PL/SQLDeveloper配置Oracle Instant Client连接Oracle数据库 文章目录 PL/SQLDeveloper配置Oracle Instant Client连接Oracle数据库 1. Oracle Instant Client下载与配置1. Oracle Instant Client下载2. Oracle Instant Client解压配置1. 解压2. 配置 2. PL/SQL Developer下载、…...

高股息打底+政策催化增强+永续经营兜底

通过分析农业银行&#xff08;政策红利高股息&#xff09;与长江电力&#xff08;垄断资源现金流堡垒&#xff09;的共性&#xff0c;提炼出以下策略框架&#xff1a; ​​1. 核心筛选标准​​ • 高股息防御性&#xff1a;股息率>3%&#xff0c;分红率稳定&#xff08;40%…...

双电机差速控制的MATLAB Simulink仿真方案,使用PWM和PID调节实现360°转向与速度控制_可复现,有问题请联系博主

以下是一个双电机差速控制的MATLAB Simulink仿真方案,使用PWM和PID调节实现360转向与速度控制。方案包含系统建模、控制策略和仿真实现。 系统模型 差速运动学模型: 线速度 ( v = \frac{v_r + v_l}{2} )角速度 ( \omega = \frac{v_r - v_l}{d} )其中 ( v_r, v_l ) 为右/左轮线…...

【Oracle】触发器

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Oracle 文章目录 1. 触发器基础概述1.1 触发器的概念与特点1.2 触发器的分类1.3 触发器的执行顺序 2. DML触发器2.1 基础DML触发器2.1.1 INSERT触发器2.1.2 UPDATE触发器2.1.3 DELETE触发器 2.2 高级DML触发器2.2.1 复合触发器2…...

基于深度学习的无人机轨迹预测

完整代码见文末 随着无人机技术的不断发展&#xff0c;无人机在农业、物流、监控等领域的应用日益广泛。精准的轨迹预测不仅能够提高无人机飞行的效率和安全性&#xff0c;还能在应对复杂环境下的突发状况时做出迅速反应。因此&#xff0c;基于深度学习的无人机轨迹预测已成为…...

git连接本地仓库以及gitee

参考:gitee创建新仓库并上传代码_gitee新建仓库导入代码-CSDN博客 git初始化以及添加git分支 在idea查看master主分支 报错 原因gitee推送更新失败问题记录&#xff1a;remote: error: hook declined to update refs/heads/master-CSDN博客 取消邮箱暴露...

使用Python和OpenCV实现图像识别与目标检测

在计算机视觉领域&#xff0c;图像识别和目标检测是两个非常重要的任务。图像识别是指识别图像中的内容&#xff0c;例如判断一张图片中是否包含某个特定物体&#xff1b;目标检测则是在图像中定位并识别多个物体的位置和类别。OpenCV是一个功能强大的开源计算机视觉库&#xf…...

麒麟v10系统的docker重大问题解决-不支持容器名称解析

今天给客户在麒麟v10Kylin-Server-V10-SP1下安装nextcloudonlyoffice的时候出现无法连接onlyoffice的问题,经过分析找到了是docker版本过低的原因,现在把解决思路和步骤分享给大家。 一、问题 用一键安装工具,给客户装好了系统,Nextcloud可以正常访问 但是访问nextcloud中的o…...

基于5G下行信号的模糊函数分析matlab仿真,对比速度模糊函数和距离模糊函数

目录 1.引言 2.算法仿真效果演示 3.数据集格式或算法参数简介 4.MATLAB部分程序 5.算法涉及理论知识概要 6.参考文献 7.完整算法代码文件获得 1.引言 模糊函数&#xff08;Ambiguity Function, AF&#xff09;是信号处理领域用于分析信号时频分辨能力的核心工具&#xf…...

Selenium自动下载浏览器驱动

为什么需要自动下载浏览器驱动&#xff1f; 血泪场景重现 新人入职第一天&#xff1a; 花3小时配置Chrome/Firefox驱动版本不匹配导致SessionNotCreatedException 浏览器自动更新后&#xff1a; 所有测试脚本突然崩溃手动查找驱动耗时长 终极解决方案&#xff1a;自动下载驱…...

数据库优化实战分享:高频场景下的性能调优技巧与案例解析

在实际开发与生产运维中&#xff0c;数据库的性能瓶颈往往是影响系统响应速度和用户体验的关键因素。尤其是在高并发访问、海量数据处理、复杂查询逻辑等高频场景下&#xff0c;数据库优化不仅仅是“锦上添花”&#xff0c;更是“雪中送炭”。本篇博文将结合实际项目经验&#…...

Redis 过期了解

Redis 版本&#xff1a;5.0 &#xff1a; 一&#xff1a;过期监听&#xff1a; Spring Data Redis 封装了 Redis 的 Pub/Sub 功能&#xff0c;提供了对 key 过期事件的监听支持。 1. 核心类&#xff1a;KeyExpirationEventMessageListener 这个抽象类是 Spring 提供的&#x…...

微信小程序前端面经

一、技术栈与编码能力&#xff08;10min&#xff09; 1. Vue 3 & Composition API Q1&#xff1a;请解释一下 ref 和 reactive 的区别&#xff1f;你在项目中是如何使用的&#xff1f; 答&#xff1a;ref是包装一个原始值或对象&#xff0c;通过.value访问&#xff0c;r…...

android 之 Tombstone

Android 系统中的 Tombstone 是记录 Native 层崩溃信息的关键日志文件&#xff0c;当应用或系统服务因严重错误&#xff08;如内存访问异常、空指针解引用等&#xff09;崩溃时自动生成。以下是其核心机制与分析方法详解&#xff1a; 一、Tombstone 的生成机制 触发条件 当 Na…...

六级作文模板笔记

旧模板 Today there is a growing awareness that mental well-being needs to be given as much attention as physical health. In the contemporary world where change is constant and knowledge is ever-expanding, mental well-being has become increasingly importan…...

JAVA理论-JAVA基础知识

1.Java 基础 知识 1.1 面向对象的特征&#xff08;了解&#xff09; 面向对象的特征&#xff1a;封装、继承、多态、抽象 封装&#xff1a;就是把对象的属性和行为&#xff08;数据&#xff09;结合为一个独立的整体&#xff0c;并尽量隐藏对象的内部细节&#xff0c;公开我希…...

免费无限使用GPT Plus、Claude Pro、Grok Super、Deepseek满血版

渗透智能-ShirtAI&#xff0c;可以免费无限使用GPT Plus、Claude Pro、Grok Super、Deepseek满血版、除此之外还能免费使用AI搜索、Gemini AI、AI照片修复、AI橡皮擦、AI去背景、AI智能抠图、AI证件照、OCR识别、在线思维导图、在线绘图工具、PDF工具箱、PDF翻译。 传送入口&a…...

SoloSpeech - 高质量语音处理模型,一键提取指定说话人音频并提升提取音频清晰度和质量 本地一键整合包下载

视频教程&#xff1a; 一个强大的语音分离和降噪软件 SoloSpeech 是由约翰霍普金斯大学、香港中文大学、南洋理工大学、清华大学及布拉格理工大学等多所高校共同主导开源的一个创新的语音处理项目&#xff0c;旨在解决在多人同时说话的环境中&#xff0c;准确提取并清晰呈现特定…...

深入解析 Java ClassLoader:揭开 JVM 动态加载的神秘面纱

大家好&#xff0c;这里是架构资源栈&#xff01;点击上方关注&#xff0c;添加“星标”&#xff0c;一起学习大厂前沿架构&#xff01; Java 之所以能实现“一次编写&#xff0c;到处运行”&#xff0c;很大程度得益于其虚拟机&#xff08;JVM&#xff09;强大的跨平台能力。…...