Java 面试题

MySQL为什么用B+树做索引?InnoDB索引深度解析

"MySQL为什么用B+树做索引,不用B树、哈希、二叉树?"

为什么面试官会问这道题

MySQL后端面试的镇场题,每场必问。面试官想听你真的理解磁盘IO、B+树的形状、以及叶子节点链表为什么对范围查询至关重要——而不是只会说"B+树好"。

如何回答

  1. 1

    先定基调:索引操作的成本是磁盘页读次数,一切索引设计都是为了减少页读。

  2. 2

    对比其他结构:二叉树层数太深(一百万数据约20层,20次IO);B树每个节点存数据,一个节点能放的key少、树会很高;B+树内部节点只存key和指针,一个页能塞约1000个key,所以树又宽又矮。

  3. 3

    给具体数字:InnoDB页16KB,一对key-pointer约15字节,一个页能放约1000个key。3层B+树就能索引约10亿行数据,最多3次页读——而且顶部1-2层会常驻InnoDB buffer pool,实际只要1次磁盘IO。

  4. 4

    讲叶子链表:所有叶子节点按key顺序用双向链表连起来,范围查询(BETWEEN、ORDER BY)顺序走叶子,不用回到根,这是SQL性能的关键。

  5. 5

    讲InnoDB特点:聚簇索引叶子存整行(主键查询一次树查找到位);二级索引叶子存主键(需要回表再走一次聚簇索引);覆盖索引把需要的列都放进二级索引,避开回表。

参考回答示例

B+树的选择本质是为了优化磁盘IO。真实数据库的索引操作成本主要在读页——InnoDB一页16KB——所以树的形状至关重要。哈希索引点查O(1),但完全不支持范围查询和ORDER BY,而这些才是SQL常规需求。二叉搜索树的层数是log以2为底,一百万数据约20层,最坏20次磁盘IO。B树通过每节点多路扇出降低了高度,但每个节点都存数据行,一个节点能放的key很有限。B+树的精髓是内部节点只存key和子指针,不存数据——所以一个16KB的页能放约1000个key。这种扇出下,3层B+树就能索引约10亿行,而且顶部1-2层常驻buffer pool,主键查询实际上一次磁盘IO就够了。第二个关键特性是叶子节点的双向链表——所有叶子按key顺序串起来,像WHERE id BETWEEN 100 AND 200这种范围查询、或ORDER BY排序,直接沿叶子顺序扫描,不用回到根重新走。这是B+树相对B树最大的优势。InnoDB里,主键定义了聚簇索引——表本身就是这棵B+树,叶子存的是整行数据。二级索引的叶子存的是主键值,所以用二级索引查询要先在二级树找到主键,再回聚簇树取整行——这就是"回表"的成本。覆盖索引就是把查询需要的所有列都包含在二级索引里,查询完全不用回表,是重要的调优手段。比如查询SELECT name, age FROM t WHERE name = ?,建idx_name_age(name, age)就能覆盖。

实用技巧

  • 要给具体数字——"3层B+树能索引10亿行"比"树很矮"有说服力十倍。

  • 准备好追问:"什么是回表?"、"什么是覆盖索引?"这两个必问。

  • 提到buffer pool缓存顶层节点,是展示你懂真实运维的信号。

  • 如果临场忘了"16KB页,约1000个key"这些数字,即答侠可以实时提示。

常见问题

MySQL支持哈希索引吗?

MEMORY引擎原生支持,InnoDB内部有自适应哈希索引(AHI)用于热点页,但主索引永远是B+树。

为什么主键查询比二级索引快?

主键是聚簇索引,一次树查找就拿到整行。二级索引要回表——先查到主键再查聚簇索引,多一次树查找。

怎么设计覆盖索引?

把查询SELECT和WHERE涉及的所有列按最左前缀顺序放进一个复合索引里。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠