Skip to content

MySQL 索引为什么用 B+ 树?与 B 树、哈希索引有什么区别? ​

🧑‍💻 面试官:MySQL 索引为什么常用 B+ 树,不用二叉搜索树?

🙋‍♂️ 我:B+ 树一个节点可以有很多分支,树更矮,读取的页通常更少。

🧑‍💻 面试官:哈希平均查找很快,为什么不全部换成哈希?

🙋‍♂️ 我:哈希适合等值查找,但不擅长有序范围查询。

🧑‍💻 面试官:那按订单号查到二级索引以后,就一定拿到了完整订单吗?你刚才说的“少读页”,少的是哪些页?

索引不只是内存中的查找题,还要解释「按页读取、范围连续、记录放在哪里」。

面试速答(60 秒版) ​

这里通常讨论的是 InnoDB 的常见索引,不能把所有 MySQL 索引都说成同一种结构。

B+ 树内部节点主要保存键和指向下一层的指针,一个页能容纳较多分支,因此树通常较矮。记录按键有序组织在叶子层,范围查询定位起点以后,可以沿叶子层继续扫描。

相比之下,普通 B 树内部节点也保存记录;哈希索引适合等值定位,但不提供同样的有序范围访问能力。

同时,InnoDB 聚簇索引叶子保存完整行,二级索引叶子包含索引列和主键。查询需要其他列时,可能还要通过主键查聚簇索引。因此,判断查询成本要看访问哪些页、扫描多少记录,以及是否需要回表。

B+树有序页访问和hash等值能力

知识点详解:数据库读一条记录,为什么要讨论“页”? ​

索引不是一次搬进内存的数组 ​

假设订单表有很多行,数据分散保存在页中。数据库会把需要的页读入缓冲池;页已在内存里时,也仍然需要在页内寻找记录。

因此,查找成本不能只看比较了多少次,还要看访问了多少页,以及是否需要从存储设备读入。

二叉树一个节点只有少量分支,规模大以后高度可能较高。B+ 树的节点可以容纳许多键和指针,一次进入一个内部页,就能选择较大范围中的下一页。树更矮,通常意味着从根到叶需要经过更少的层。

这不是说每次查询都一定产生同样次数的磁盘 I/O。上层索引页可能已经缓存在内存,真实成本还受缓存命中和存储影响。

内部节点和叶子节点,放的内容不同 ​

在常见 B+ 树中,内部节点负责导航,记录集中在叶子层。内部页不放完整行,就有机会容纳更多索引键,增加分支数量。

普通 B 树的记录可以出现在内部节点和叶子节点。两者都可以保持平衡,不能把 B 树说成天然失衡或一定很慢。

B+ 树把记录组织在有序的叶子层,范围读取比较顺畅。对于数据库常见的范围、排序和批量访问,这种安排比较合适。MySQL 的索引结构说明介绍了 InnoDB 聚簇与二级索引的具体存储。

查一段订单号,为什么不必从根开始查每一条? ​

假设要查询编号从 1000 到 1100 的订单。B+ 树先定位范围起点,再沿叶子层读取后续键,直到越过上界。

这些键有序排列,因此范围边界可以指导扫描。但“逻辑上相邻”不代表磁盘上每个页都物理连续,也不能保证所有页都已在缓冲池里。

哈希索引则按哈希值定位桶。编号 1000 和 1001 不一定落到相邻位置,所以它不具备同样的范围顺序。MySQL 某些引擎支持哈希索引,InnoDB 也有自适应哈希等机制,但不能因此把常见用户索引理解成全部采用哈希。B-Tree 与 Hash 比较说明了访问能力的差异。

查二级索引,为什么还可能“回表”? ​

假设订单表主键是 id,另建了用户编号索引。二级索引叶子里可以找到用户编号和相应主键,但完整订单信息放在聚簇索引叶子中。

如果查询还要订单备注,就可能通过主键再查聚簇索引。这一步通常称为回表。

如果需要的字段都能从二级索引获取,就有机会使用覆盖索引,减少这次额外访问。但覆盖索引并不是越宽越好:列更多,索引页更大,写入和维护成本也更高。

因此,解释“索引为什么快”时,要顺着实际查询走完,不能在二级索引找到键以后就停下。

二级索引到主键再找完整行

面试官继续追问 ​

主键越长,会有什么影响? ​

二级索引需要保存主键,所以较长主键会让多个二级索引一起变大。

同一个页能放的记录可能减少,缓存效率和维护成本也会受到影响。是否选择某种主键,还要结合生成方式、写入分布和业务约束,不是单凭长度决定。

用了索引,就一定比全表扫描快吗? ​

不一定。如果要取出大部分行,沿二级索引读取再大量回表,可能比扫描聚簇索引更贵。

优化器会估算代价。应结合执行计划与实际数据分布检查,不能看见全表扫描就直接认定数据库做错了。

如何验证某个索引值得保留? ​

检查它支持哪些高频查询,减少了多少扫描和回表,同时比较写入开销与存储占用。

只在空表上跑一次查询,看不出真实代价。需要有代表性的行数和分布,还要观察索引有没有重复建设。

面试速记卡 ​

  • B+ 树:多路、平衡,内部导航,叶子层有序存储记录。
  • 页访问:树高提供线索,实际 I/O 还受缓冲池影响。
  • 范围查询:定位起点后沿叶子层继续扫描。
  • 哈希区别:擅长等值定位,不提供同样的有序范围能力。
  • InnoDB:聚簇叶子是行,二级叶子包含主键,必要时回表。

基于 VitePress 构建 | 记录真实开发与 AI 协作过程