mysql索引为什么会选择B+树结构_InnoDB与MyISAM索引实现异同

陌涛姑娘_6260

陌涛姑娘_6260

2026-05-02

930人浏览

原创

B+树是MySQL索引的首选结构,因其在磁盘I/O效率、范围查询支持和数据稳定性三方面优于哈希表、二叉树及B树:哈希索引仅支持等值查询且不支持范围扫描;B树非叶节点存数据导致树高更高、范围查询需频繁回溯;而B+树所有数据集中于有序链表连接的叶子节点,既降低树高减少I/O,又使范围查询和顺序遍历高效稳定。

mysql索引为什么会选择b+树结构_innodb与myisam索引实现异同

B+树是MySQL索引的默认且事实标准结构,不是因为“它很酷”,而是因为磁盘IO、范围查询、并发稳定性这三件事,B树和Hash都扛不住。

为什么不用Hash索引做主索引?

Hash索引只适合=等值查询,遇到WHERE id > 100或ORDER BY created_at就直接退化成全表扫描。InnoDB根本不支持Hash作为主索引(虽然有自适应哈希索引,但那是内部优化,不可控)。MyISAM压根不支持Hash索引。另外,Hash碰撞会导致链表拉长,查询退化为线性扫描——这点在高基数字段上尤其明显。

常见错误现象:EXPLAIN显示type: ALL,明明建了索引却没走;SELECT ... WHERE status IN ('A','B')响应慢得反常。

  • MyISAM和InnoDB都不允许你显式声明HASH为主键索引类型
  • 即使你在Memory引擎里用HASH,也别指望它能替代B+Tree处理业务主键
  • InnoDB的自适应哈希索引是自动触发的,无法配置,也不该依赖它解决设计问题

为什么不是B树而是B+树?

B+树把所有数据都塞进叶子节点,并让叶子节点用双向链表串起来。这样做的直接好处是:每次磁盘IO能读更多关键字(非叶节点不存数据,只存key),同时范围扫描时不用反复回溯父节点——顺着叶子链表扫就行。

举个实际影响:假设一个页(16KB)能存500个key,B树每个节点还要存data指针,可能只能放300个;B+树非叶节点纯key,就能放450个。树高降低一层,意味着一次范围查询少一次磁盘IO——这对SSD尚可忽略,对机械盘就是百毫秒级差异。

  • B+树所有查询路径长度一致,不存在“运气好走左子树快、运气差走右子树慢”的情况
  • 插入/删除时,B+树只需调整叶子链表指针,B树要频繁挪动data域,分裂代价更高
  • InnoDB的聚簇索引要求数据物理有序,B+树天然适配这个约束

InnoDB和MyISAM的B+树到底差在哪?

核心就一条:InnoDB的主键索引叶子节点存的是**整行数据**,MyISAM的主键索引叶子节点存的是**行号(row number)或文件偏移量**。这就导致二者行为完全分化。

比如执行SELECT * FROM t WHERE name = 'lisi'(name是普通索引):

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载
  • MyISAM:先查name索引树拿到行号 → 再按行号直接跳转到数据文件读整行(1次索引IO + 1次数据IO)
  • InnoDB:先查name索引树拿到主键值(比如id=5)→ 再查主键索引树定位到整行数据(2次索引IO,无额外数据文件访问)

这就是常说的“InnoDB回表要查主键”——但注意,它不是去查另一个文件,而是再走一遍B+Tree。所以SELECT id, name这种覆盖索引查询,InnoDB连第二次索引查找都省了。

容易踩的坑:SELECT *在InnoDB上如果没走覆盖索引,等于强制触发二次B+Tree查找;而MyISAM哪怕SELECT *,只要索引存在,就是固定两次IO(索引+数据),跟字段数无关。

什么时候B+树也会失效?

B+树再好,也救不了设计失当的查询。最典型的是前导模糊匹配:LIKE '%abc'会让整个索引失效;函数包装字段:WHERE YEAR(created_at) = 2025,MySQL无法用索引做范围下推;还有隐式类型转换:WHERE user_id = '123'(user_id是INT)会放弃索引。

更隐蔽的问题是:InnoDB二级索引存储的是主键值,如果你用VARCHAR(255)甚至UUID做主键,那每个二级索引的叶子节点都要存一份超长主键——索引体积暴增,缓存命中率暴跌,查询反而变慢。

真正关键的不是“B+树多厉害”,而是你建的索引是否匹配查询模式、主键是否足够紧凑、有没有无意中写出索引无法下推的条件——这些地方一错,B+树再稳也没用。

相关专题

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

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

2023.10.12

4543

8

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

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

2023.10.27

951

4

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

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

2024.02.23

1189

5

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

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

2024.03.06

6501

10

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

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

2024.03.06

3283

4

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

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

2024.04.07

6460

11

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

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

2024.04.29

8861

6

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

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

2024.04.29

1210

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1052

5

热门下载

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

精品课程

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

共1课时 | 192人学习