Skip to content
掌握度

对比小林《为什么采用 B+ 树》《索引常见面试题》《索引失效》、JavaGuide MySQL 索引详解与面渣逆袭《MySQL 索引》(侧边栏进入)(二哥索引页为空壳,无对应内容)。

多版对比 ​

​「为什么是 B+ 树」,小林的推导链最完整​:以磁盘 I/O 为主线逐层排除——二叉搜索树极端情况退化成链表;AVL/红黑树仍是二叉,树高≈磁盘 I/O 次数;B 树矮胖但节点和数据一起存,单页放的索引项少;​B+ 树非叶子节点只存索引​,单页能放更多指针所以更矮,叶子节点双向链表天然支持范围查询,冗余索引让增删开销更小。面渣给了可背的算式:16K 页 ÷ 14 字节 ≈ 1170 个指针,三层 ≈ 1170² × 16 ≈ 2000 万行。

​「2000 万行上限」的处理,两边互补​:面渣把算式当结论;小林用实验质疑「单表 2000w 是上限」的说法——层数取决于页大小和行大小,四层也能跑,关键看缓冲池命中率。

索引失效,JG 有一个关键视角升级​:小林按现象罗列六类(左右模糊、函数、表达式、隐式转换、非最左、OR 一侧无索引),隐式转换的原理是等价于对列加了 CAST 函数;JG 把失效分成两类——​「破坏 B+ 树有序性」是真失效,「优化器成本决策」(回表代价高、IN 条件过多估算失真时主动选全表扫描)不算真失效​,判断要靠 EXPLAIN 而不是背规则。

各自独有​:JG——Hash/B 树/B+ 树全选型对比、MyISAM 非聚簇与 InnoDB 聚簇的实现差异、主键忌过长和无序、索引下推 ICP;小林——回表就是查两棵 B+ 树、覆盖索引只查一棵、最左匹配的本质是「全局无序、局部有序」、count(*) 与 count(1)。

最优题解 ​

为什么用 B+ 树,从磁盘 I/O 推:索引查询的代价约等于树高乘以每次页读取。二叉树太高;B 树虽然矮,但非叶子节点也要存数据,一个 16K 页放不下几个分支;B+ 树非叶子只存键和指针,三层就能容纳约两千万行(1170²×16 的量级),叶子之间双向链表又天然支持范围扫描——所以是「矮胖 + 有序 + 链表」三合一。

使用层面记三组概念:聚簇索引叶子存整行,二级索引叶子存主键,用二级索引查非索引列就要回表​(查两棵树),查询列全在索引里就是覆盖索引​(只查一棵);联合索引遵循最左前缀​,本质是「全局无序、局部有序」;​失效分两类——破坏有序性的(函数、隐式转换、左右模糊、非最左)是真失效,而优化器基于成本选择全表扫描不算失效,判断靠 EXPLAIN 而不是背口诀。

追问链 ​

追问:为什么不用 Hash 索引或红黑树?​ 参考答:Hash 等值查询 O(1) 但不支持范围和排序,哈希冲突还要拉链;红黑树是二叉的,百万数据树高二十层,每层一次磁盘 I/O;B+ 树三到四层就够,且叶子链表天然服务范围查询。

追问:单表 2000 万行就要分表吗?​ 参考答:不是硬阈值——层数由页大小和行大小决定,2000 万是三层 B+ 树的量级估算;是否分表看缓冲池命中率、增长速度和查询模式,四层树在命中率高时也完全可用。

我的理解 ​

这题的性价比最高的答法:用「树高 = 磁盘 I/O 次数」把选型推一遍(小林链路),用「回表 = 查两棵树」串起聚簇/覆盖/最左(两家共识),最后落 JG 的「真失效 vs 成本决策」分类——这一下就和其他背口诀的候选人拉开差距。面渣的 1170 算式留作记忆锚点,但「2000 万上限」要按小林的口径主动纠偏。

本站仅供个人学习使用,请勿外传