0

0

SQL B+ 树索引的核心思想

冷漠man

冷漠man

发布时间:2026-01-24 16:18:56

|

800人浏览过

|

来源于php中文网

原创

B+树是专为磁盘I/O优化的多叉树结构,非叶子节点仅存键值和指针以降低树高,所有数据存储在叶子层且通过双向链表连接,支持高效范围查询与顺序扫描;其联合索引依赖最左前缀原则,且索引失效源于破坏键值有序性的操作。

sql b+ 树索引的核心思想

为什么B+树不是B树,也不是二叉树

B+树是专为磁盘I/O优化的结构,不是为了内存查找快而设计的。它放弃“每个节点存数据”的直觉,转而让非叶子节点只存键值子节点指针,这样一页(如InnoDB默认16KB)能塞下更多分支,树高自然压得更低——千万级数据通常只要3~4层,意味着最多4次磁盘读就能定位到记录。

  • 二叉树在数据库里基本不用:树太高,一次查询可能要几十次磁盘IO
  • 平衡二叉树(AVL)仍只有2叉,空间利用率低,页内键值数少,树高难压缩
  • B树虽支持多叉,但非叶子节点也存数据,挤占了本可用于扩大扇出的存储空间
  • B+树把所有数据“沉”到叶子层,非叶子层纯粹做导航,这是它矮胖、抗写、适合范围查询的根本原因

叶子节点连成双向链表到底有什么用

这个设计不是锦上添花,而是解决真实场景问题的关键:比如SELECT * FROM orders WHERE create_time BETWEEN '2025-01-01' AND '2025-01-31',没有链表就得反复回树顶找下一个范围起点;有了next指针,查到第一个匹配叶子节点后,直接顺序往后扫,全程不跳回非叶子层。

  • 范围查询(BETWEEN>=LIKE 'abc%')性能跃升,避免多次随机IO
  • ORDER BY + LIMIT 场景天然受益,例如翻页查询ORDER BY id LIMIT 10000,20
  • 聚簇索引下,叶子节点存的是完整行数据,链表即物理顺序,极大减少磁盘寻道
  • 注意:二级索引叶子存的是主键值而非整行,所以范围扫描后还需回表——这就是覆盖索引要解决的问题

联合索引为什么必须遵守最左前缀原则

因为B+树的搜索路径是单向递进的:从根节点开始,每一层都只按当前层级的键做二分查找,无法跳过某一层去“猜”下一层该比谁。联合索引(a, b, c)在内存中构建的是一棵以a为第一排序维度、b为第二、c为第三的树,a不等价于“过滤条件可选”,而是搜索入口的强制门槛。

蕉点AI
蕉点AI

AI电商商品图生成平台 | 智能商品素材制作工具

下载
  • 支持:WHERE a = ?WHERE a = ? AND b > ?WHERE a = ? AND b = ? AND c IN (?,?)
  • 不支持:WHERE b = ?(没a,根本进不了树的第二层)、WHERE a > ? AND c = ?c在第三层,但第二层b未定界,无法确定c的有序区间)
  • 隐式陷阱:WHERE a = ? AND c = ?看似用了两个字段,实际只能用上ac被跳过,变成索引扫描而非索引查找

索引失效的三个典型瞬间

不是建了索引就万事大吉。B+树依赖“值的有序性”工作,任何破坏这种有序性的操作都会让引擎弃用索引,退化为全表扫描。

  • WHERE name LIKE '%john':前导通配符导致无法利用B+树叶节点的有序链表,必须逐行匹配
  • WHERE YEAR(create_time) = 2025:函数计算使索引列create_time原始值不可见,优化器无法将查询条件映射到树中键值区间
  • WHERE user_id = '123'user_id是INT类型):隐式类型转换触发全表扫描,MySQL会把每行user_id转成字符串再比,索引失效

这些不是配置问题,也不是版本bug,而是B+树结构本身决定的硬约束——它只认原始、有序、未加工的键值序列。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

685

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

324

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

348

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1117

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

359

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

717

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

577

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

419

2024.04.29

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.9万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 808人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号