MySQL索引背后的B+树奥秘

MySQL 索引实现机制深度解析

MySQL 索引的核心数据结构是 B+树。这种设计是数据库领域数十年优化的结果,完美平衡了磁盘 I/O 效率、范围查询性能和存储利用率。以下是关键要点:


一、为什么选择 B+树而非其他结构?
数据结构劣势B+树优势
二叉搜索树深度不可控,极端情况退化成链表(O(n))多路平衡,高度稳定(O(log n))
B 树数据存储在内部节点,范围查询效率低数据全存叶子节点,顺序访问高效
哈希索引仅支持等值查询,不支持范围查询,内存占用高天然支持范围查询(>、<、BETWEEN)和排序
跳表磁盘 I/O 不友好,存储空间放大磁盘页对齐设计,减少 I/O 次数

B+树核心优势

  • 树高通常仅 3-4 层(千万级数据)
  • 叶子节点形成有序双向链表,范围查询极快
  • 内部节点只存键值(不存数据),提升节点容量

二、B+树索引的物理结构

以 InnoDB 存储引擎为例:

根节点
内部节点
内部节点
叶子节点
叶子节点
叶子节点
叶子节点
  1. 叶子节点(Leaf Nodes)

    • 存储完整数据行(聚簇索引)或主键值(二级索引)
    • 通过双向链表连接,支持顺序扫描
    • 默认每页 16KB(可通过 innodb_page_size 调整)
  2. 内部节点(Internal Nodes)

    • 仅存储索引键值 + 子节点指针
    • 单节点可存储上千个键值(减少树高)

三、索引类型与 B+树实现差异
1. 聚簇索引(Clustered Index)
  • 物理存储顺序与索引顺序一致
  • 叶子节点直接存数据行
  • 每表只有一个聚簇索引(通常为主键)
CREATE TABLE users (id INT PRIMARY KEY,  -- 聚簇索引name VARCHAR(50),INDEX idx_name(name) -- 二级索引
);
2. 二级索引(Secondary Index)
  • 叶子节点存储主键值(非数据行)
  • 查询需回表:先查二级索引 → 再查聚簇索引
  • 覆盖索引可避免回表(索引包含所有查询字段)
-- 回表查询(需两次B+树查找)
SELECT * FROM users WHERE name = 'Alice';-- 覆盖索引(避免回表)
SELECT id FROM users WHERE name = 'Alice';
3. 联合索引(Composite Index)
  • 按字段顺序构建 B+树
  • 最左前缀匹配原则生效
-- 创建联合索引
CREATE INDEX idx_age_name ON users(age, name);-- 生效场景
SELECT * FROM users WHERE age = 30;                 -- ✅ 使用索引
SELECT * FROM users WHERE age = 30 AND name = 'Bob';-- ✅ 使用索引
SELECT * FROM users WHERE name = 'Bob';             -- ❌ 不满足最左前缀

四、B+树操作原理
插入流程
  1. 定位到叶子节点插入位置
  2. 若节点未满 → 直接插入
  3. 若节点已满 → 分裂节点(50%数据移入新页)
  4. 向上递归更新父节点指针
删除流程
  1. 定位叶子节点中的记录
  2. 设置删除标记(InnoDB 使用 purge 线程异步清理)
  3. 若节点利用率过低 → 合并相邻节点

五、性能优化实践
  1. 控制索引字段长度

    • 使用前缀索引:INDEX idx_name(name(10))
    • 整型优于字符串(更小键值 → 更高节点密度)
  2. 避免索引分裂热点

    • 不使用单调递增主键(如 UUID v4 代替自增 ID)
    CREATE TABLE orders (id BINARY(16) PRIMARY KEY  -- UUID v4
    );
    
  3. 索引选择性优化

    • 选择性 > 30% 时索引才有效
    -- 计算字段选择性
    SELECT COUNT(DISTINCT status)/COUNT(*) FROM orders; 
    

六、其他索引类型的实现
索引类型实现结构适用场景
全文索引(FULLTEXT)倒排索引MATCH(content) AGAINST('keyword')
空间索引(SPATIAL)R 树GIS 地理位置查询
内存表哈希索引哈希表临时表/等值查询高频场景

七、诊断索引使用情况
1. 查看索引树高度
-- InnoDB 索引统计
ANALYZE TABLE users;
SELECT index_name, stat_value AS pages
FROM mysql.innodb_index_stats 
WHERE table_name = 'users'
AND stat_name = 'n_leaf_pages';
  • 树高计算公式:h = log_N(叶子页数)
    (N = 单页可存储键值数,通常 1000+)
2. EXPLAIN 解析索引使用
EXPLAIN SELECT * FROM users WHERE age > 25;
  • type: ref → 索引查找
  • Extra: Using index → 覆盖索引

总结:MySQL 索引设计哲学

  1. 磁盘友好优先
    B+树节点大小 = 磁盘页大小(16KB),最大化顺序 I/O
  2. 写优化让步于读优化
    索引维护成本(分裂/合并)换取高效查询
  3. 空间换时间
    索引占存储空间 20%-30%,但提升查询速度 10-100 倍

黄金法则

  • 更新频繁的表避免过多索引
  • 联合索引字段顺序:高选择性在前
  • 长文本用前缀索引 + 全文索引互补

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

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

相关文章

k8s通过NUMA亲和分配GPU和VF接口

问题 一般情况下&#xff0c;sriov插件和gpu分配插件是单独工作的&#xff0c;网卡和GPU没有根据连接关系分配 如果一个节点起了多个容器&#xff0c;会造成GPU和网卡的通信瓶颈 修改 如果一个点起两个容器&#xff0c;可以按照NUMA亲和来分配 修改kubelet配置文件/var/lib/kub…

qemu-img 扩容虚拟机磁盘后扩容文件系统

在给磁盘映像扩容前需要关闭虚拟机1. 关闭虚拟机 [rootkvm1 opt]# virsh shutdown centos7.9 [rootkvm1 opt]# virsh list --allId Name State ----------------------------- centos7.9 shut off[rootkvm1 opt]# qemu-img info /var/lib/libvirt/images/centos…

Winwos上编译opencv的GPU版本推理yolov8

1.工具 VS2019 opencv4.7.0 opencv_contrib4.7.0 Cmake3.27.0 cudnn-windows-x86_64-8.5.0.96_cuda11-archive 2.具体流程 1.配置路径和编译器后点击configure 2.提前下载相关的包&#xff0c;如下图所示 3.第一次configure完成后&#xff0c;需要再配置编译选项 在编译…

C语言案例《猜拳游戏》

《猜拳游戏》 游戏说明 一、游戏简介 本游戏为猜拳对战类游戏&#xff0c;玩家可选择不同对手进行石头、剪刀、布的猜拳对决&#xff0c;支持重复游玩&#xff0c;直至玩家选择退出。 二、游戏流程 选择对手 游戏开始后&#xff0c;玩家需从 3 名对手中选择 1 名进行对战&#…

使用python的头文件Matplotlib时plt.show()【标题字体过小】问题根源与解决方案

使用python的头文件Matplotlib时plt.show【标题字体过小】问题根源与解决方案1. 问题复现2. 问题分析3. 解决方案方案一&#xff08;推荐&#xff09;&#xff1a;使用 fig.suptitle 结合 subplots_adjust方案二&#xff1a;以保存文件函数plt.savefig为准方案三&#xff1a;不…

全面解析MySQL(3)——CRUD进阶与数据库约束:构建健壮数据系统的基石

> 本文将带你深入探索MySQL的进阶CRUD操作与核心约束机制,用设计原则的视角揭示数据库如何保障数据世界的秩序。 ### 一、进阶CRUD:数据操作的精密工具 #### 1. 精准筛选:WHERE子句的深度运用 ```sql -- 基础筛选:价格大于50的菜品 SELECT * FROM dishes WHERE pric…

使用Redis实现MySQL的数据缓存

使用Redis来实现/mySQL的数据缓存的架构1&#xff1a;目标数据从mySQL读取数据或者从Redis读取数据 2&#xff1a;使用cannal监控mySQL&#xff1a;canal-server可以对mysql的blog实行拉取&#xff0c;可以拉去blog里面的(增&#xff0c;删&#xff0c;改等操作&#xff0c;查询…

linux配置ntp时间同步

目录 1.设置时区 2.安装chrony时间同步工具 3.修改chrony配置文件,添加阿里云NTP服务器作为时钟源 4.重启chrony服务&#xff0c;并查看同步结果 1.设置时区 timedatectl set-timezone Asia/Shanghai 2.安装chrony时间同步工具 apt install chrony -y&#xff08;dnf ins…

powershell 实现批量把文件夹下的bmp文件转换为jpg

以下是一个使用PowerShell将BMP图像批量转换为JPG&#xff08;质量85&#xff09;的脚本&#xff1a; <# .SYNOPSIS批量将BMP图像转换为JPG格式&#xff08;质量85&#xff09; .DESCRIPTION此脚本会遍历指定文件夹中的所有BMP文件&#xff0c;并将它们转换为JPG格式&#x…

星图云开发者平台新功能速递 | 页面编辑器:全场景编辑器,提供系统全面的解决方案

在数字化转型的浪潮下&#xff0c;高效的低代码开发工具成为企业和开发者的刚需&#xff0c;其需要针对Web、APP、H5等不同终端快速构建应用。但不同场景的开发往往需要不同的工具和技术栈&#xff0c;导致开发效率低、协作成本高。星图云开发者平台创新推出多类型页面专用编辑…

激活函数Focal Loss 详解​

Focal Loss 详解​1. 背景​Focal Loss 是由 Lin et al. (2017) 在论文 《Focal Loss for Dense Object Detection》 中提出的一种损失函数&#xff0c;主要用于解决 目标检测&#xff08;Object Detection&#xff09; 中的 类别不平衡问题&#xff0c;特别是在 One-Stage 检测…

Python 链接各种中间件[Mysql\redis\mssql\tdengine]

文章目录链接参数设置logger 日志redis 链接mysql 链接emqx 链接mssql 链接tdengine 链接采集OPCUA的点表的配置信息设备点表OPCUA 采集 数据程序数据采集逻辑链接参数 import randomtdengine_connection_params {username: root,password: taosdata,host: 127.0.0.1,port: 6…

C Primer Plus 第6版 编程练习——第11章(上)

本章共16题&#xff0c;分上中下三篇1.设计并测试一个函数&#xff0c;从输入中获取n个字符&#xff08;包括空白、制表符、换行符)&#xff0c;把结果存储在一个数组里&#xff0c;它的地址被传递作为一个参数。int get_n_char(char arr[], int n) {int i 0;char ch;while (i…

Java开发岗面试记录合集

一、Java 核心1. 基础语法final关键字的作用修饰类&#xff1a;类不可被继承&#xff08;如String类&#xff09;&#xff0c;保证类的稳定性和安全性。修饰方法&#xff1a;方法不可被重写&#xff08;防止子类篡改父类核心逻辑&#xff0c;如工具类方法&#xff09;。修饰变量…

Linux 系统时间设置(date 和 ntpdate)-linux028

date 命令&#xff1a;查看或设置系统时间1. 查看当前时间date示例输出&#xff1a;Tue Mar 4 01:36:45 CST 20142. 设置时间&#xff08;不设置日期&#xff09;date -s 09:38:40设置后输出&#xff1a;Tue Mar 4 09:38:40 CST 20143. 设置完整日期和时间&#xff08;推荐格…

iOS上使用WebRTC推拉流的案例

一、库集成 首先&#xff0c;确保在你的 Podfile 中添加依赖&#xff1a; pod GoogleWebRTC然后执行 pod install 安装库。 二、代码示例 2.1、权限配置&#xff1a;在 Info.plist 中添加摄像头、麦克风权限 <!-- 需要在 Info.plist 中添加以下权限 --> <key>NSCam…

API: return response as HTML table

想要把response table变成HTML的table&#xff0c;即想达到下面这种的话<table boarder"1" style"width:100%; boarder-collapse: collapse; text-align:left"><tr><th>Customer</th><th>Date</th><th>Debit Am…

OneNote 当前无法同步笔记。将继续尝试。 (错误代码: 0xE00009C8 bb0ur)问题解决

之前因为同步错误&#xff0c;导致OneNote一个笔记本内容全部消失&#xff0c;笔记本内容如下图同步状态和错误如下&#xff1a;提醒错误为&#xff1a;OneNote 当前无法同步笔记。将继续尝试。 (错误代码: 0xE00009C8 bb0ur)当时心态有点崩&#xff0c;也是查了好些资料&#…

OneCode3.0 Gallery 组件前后端映射机制:从注解配置到前端渲染的完整链路

一、注解体系与前端组件的映射基础 ​ OneCode Gallery 组件实现了 Java 注解与前端 UI 组件的深度绑定&#xff0c;通过GalleryAnnotation、GalleryItemAnnotation和GalleryViewAnnotation三个核心注解&#xff0c;构建了从后端配置到前端渲染的完整链路。这种映射机制的核心价…

规则分配脚本

需求&#xff1a; 1.根据用户编写的要报规则,去mysql库里SysManage_Rule表获取已经启用的规则作为条件&#xff08;例如[{“field”: “关键词”, “logic”: “AND”, “value”: “阿尔法”, “operator”: “”&#xff0c;, “assign_user”: “user222”}]&#xff09;条…