真实面经题目 · 原创解析
MySQL B+ 树索引的实现
这题考察 InnoDB 如何用页式 B+ 树降低磁盘 I/O,并把等值查询、范围扫描、聚簇索引、二级索引和回表串成一条完整链路。
真实面经题目 · 原创解析
这题考察 InnoDB 如何用页式 B+ 树降低磁盘 I/O,并把等值查询、范围扫描、聚簇索引、二级索引和回表串成一条完整链路。
InnoDB 的索引通常用 B+ 树组织,节点按页存储。非叶子页保存索引键和子页指针,叶子页按键值有序;等值查询从根页逐层定位到叶子页,范围查询先找到起点,再沿叶子页之间的有序链表顺序扫描。聚簇索引的叶子页保存整行记录,二级索引的叶子页保存二级索引键和主键值,所以二级索引查不到所需列时要拿主键回到聚簇索引取行。选择 B+ 树不是因为它抽象上最平衡,而是因为分叉高、树高低、顺序扫描友好,适合数据库的页式磁盘访问。
数据库索引首先要减少随机 I/O。InnoDB 把索引节点放在固定大小的数据页里,一个页能放很多 key 和指针,因此 B+ 树的 fanout 很高,几层树就能覆盖大量数据。
非叶子页主要保存分隔 key 和子页指针,不保存完整行。查找时在当前页内定位分支,再跳到下一层页;这让每一层访问都尽量变成一次页定位。
所有真实索引项都在叶子页,叶子页按 key 有序,并通过前后指针连接。等值查询落到一个叶子位置,范围查询则从起点开始沿叶子链表连续扫描。
聚簇索引按主键组织表数据,叶子页直接存整行;二级索引叶子页存二级 key 和主键。二级索引如果不能覆盖查询字段,就要用主键再次查聚簇索引,这就是回表。
索引不是免费加速。插入、删除、更新索引列时要维护 B+ 树;随机主键或无序写入可能触发页分裂、页合并和碎片,影响写性能和缓存命中。
红黑树分叉少,数据量大时高度更高,随机 I/O 次数多。B+ 树一个页能容纳大量 key,树高低,更符合磁盘和页缓存的访问模型。
B+ 树把数据项集中在叶子页,并让叶子页有序相连。范围查询只要定位起点,就能顺序扫描叶子链表;B 树数据分散在各层,范围遍历更复杂。
查询所需字段都能从二级索引叶子页拿到时就是覆盖索引,不需要再查聚簇索引。典型场景是 select 的列都包含在联合索引中。
自增主键大多追加到索引右侧,页分裂少;随机 UUID 会分散插入到各个叶子页,更容易造成页分裂、碎片和缓存命中下降。