B+树存储结构 📅 2026/6/16 12:46:04 是的InnoDB 的聚簇索引 BTree 中只有叶子节点最底层保存完整数据记录非叶子节点根节点和中间节点只保存索引信息用于导航查找。假设有一个三层 BTree[根节点] 100 | 200 | 300 / | \ / | \ [中间节点] [中间节点] [中间节点] 50|80 150|180 250|280 / | \ / | \ / | \ [叶子节点][叶子节点][叶子节点]...第一层Root 根节点存储主键值索引键 子节点页指针例如100 | 200 | 300表示id 100 100 id 200 200 id 300 id 300以及对应子节点所在的数据页地址。不存完整数据。第二层非叶子节点存储索引键 下一层页指针例如50 | 80表示id 50 50 id 80 id 80仍然不存完整数据。第三层叶子节点聚簇索引叶子节点(id1,nameTom,age18) (id2,nameJack,age20) (id3,nameLucy,age22)存储的是整行记录例如主键 其它列 事务信息 隐藏列为什么非叶子节点不存完整数据为了提高扇出Fan Out。假设情况1非叶子节点只存 keyid一个16KB页可以放1000多个key树会非常矮1000 1000 × 1000 100万 1000 × 1000 × 1000 10亿三层就能管理十亿条记录。情况2非叶子节点存完整数据例如id name phone address ...每条记录变大。16KB页可能只能放几十条树高度会迅速增加。查询磁盘IO次数也增加。所以BTree设计成非叶子节点 只存索引键 叶子节点 存真实数据聚簇索引查找过程例如SELECT * FROM user WHERE id 150;执行过程Root 100 | 200 | 300 ↓ Middle 150 | 180 ↓ Leaf (id150,nameTom,...)查找路径根节点 ↓ 中间节点 ↓ 叶子节点找到数据。如果是普通索引呢例如create index idx_name on user(name);叶子节点就不一样了。Tom - 1 Jack - 2 Lucy - 3叶子节点保存name 主键id而不是完整数据。因此select * from user where nameTom;需要name索引树 ↓ 得到 id1 ↓ 主键索引树 ↓ 得到完整记录这就是回表。面试一句话总结InnoDB 的 BTree 中根节点和中间节点只保存索引键值以及子节点页指针用于缩小查找范围只有叶子节点才保存数据。对于聚簇索引叶子节点保存完整行记录对于二级索引叶子节点保存索引列值和主键值因此查询时可能需要回表。