【第5天】每天一个MySQL知识点,百日打怪升级

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 本文是MySQL索引核心篇,由10年经验DBA精讲B+树原理。深入剖析为何选B+树而非B树/二叉树/哈希表,详解其非叶节点仅存key、叶子双向链表、聚簇与二级索引结构,并结合回表、覆盖索引、页分裂等实战场景,直击面试高频考点。(239字)

索引基础:B+树详解


大家好,我是一名拥有10年以上经验的DBA老兵。

做这个系列,源于一个朴素的愿望:把踩过的坑、总结的经验系统化输出,希望能帮到刚入行或想进阶的兄弟们。

让我们开始今天的第5天内容。


背景引入

💡 说白了:索引就是一本书的目录。没有目录,你想找"事务"这个词,只能一页一页翻;有了目录,直接翻到对应页码。

很多同学知道索引能加速查询,但面试官一问"B+树为什么比B树适合做索引?""为什么不用二叉树?"——就懵了。

今天的目标:搞懂B+树结构,面试必问!


核心概念

一、没有索引会怎样?

没有索引时,MySQL只能全表扫描——从第一行开始,逐行对比,直到找到目标。

-- 没有索引时,查找name='张三'要扫描全表
SELECT * FROM user WHERE name = '张三';

-- EXPLAIN 查看执行结果(type=ALL,说明全表扫描)
-- type列值:ALL → 全表扫描,性能最差

假设一张表100万行,找一个值最多要对比100万次。这就是为什么索引这么重要。


二、为什么是B+树?

面试官喜欢问:为什么MySQL索引用B+树,而不是二叉树、哈希表?

我们逐个对比:

数据结构 查找复杂度 适合场景 不适合做索引的原因
二叉搜索树 O(log n) 内存查找 树太高,磁盘IO多
哈希表 O(1) 等值查找 不支持范围查询
B树 O(log n) 早期数据库 非叶子节点存数据,一次IO拿到的key少
B+树 O(log n) MySQL InnoDB ✅ 叶子节点存数据,非叶子节点只存key

💡 说白了:B+树就像一栋楼——电梯口(非叶子节点)只放楼层号,每间房(叶子节点)放真正的数据。电梯口越小,一层能放的楼层号越多,树就越矮,IO就越少。


三、B+树的关键特征

3.1 非叶子节点只存key,不存数据

好处:非叶子节点只存key,一个页(16KB)能存更多key,树更矮,IO更少。

3.2 叶子节点用双向链表连接

这是B+树和B树最大的区别——B+树的叶子之间有指针,B树没有

好处

  • 范围查询极快:找到起点后,顺着链表往后扫就行
  • 排序查询天然有序:ORDER BY不用额外排序

💡 说白了:B+树的叶子像一排人手拉手,找到第一个人,后面的跟着就出来了。B树呢?每找一个人都要重新回上一层找,效率差远了。

面试必问

  • B+树和B树有什么区别?
  • 为什么MySQL用B+树而不是B树做索引?

📝 面试解答

Q: B+树和B树有什么区别?

image.png

image.png

三个核心区别:

  • 非叶子节点:B+树只存key,B树存key+数据 → B+树一个页能存更多key,树更矮
  • 叶子节点:B+树所有数据都在叶子,B树数据分散在各层 → B+树查询稳定,都是O(log n)
  • 叶子链表:B+树叶子之间有双向链表,B树没有 → B+树范围查询极快

Q: 为什么MySQL用B+树而不是B树做索引?

  1. IO更少:B+树非叶子只存key,同样16KB的页能存更多key,树更矮,IO次数更少
  2. 范围查询更快:叶子之间有链表,找到起点后顺着扫就行;B树要中序遍历
  3. 查询更稳定:所有数据都在叶子节点,每次查询路径长度一样

四、InnoDB的索引结构

InnoDB有两种索引:聚簇索引二级索引

4.1 聚簇索引(主键索引)

聚簇索引的叶子节点存的是整行数据

image.png

💡 聚簇索引 = 数据本身。InnoDB的数据就是按主键顺序存的,所以主键查询是最快的

4.2 二级索引(非主键索引)

二级索引的叶子节点存的是主键值,不是整行数据。

image.png

查name='张三',先用二级索引找到主键id=30,再回聚簇索引找整行数据——这个过程叫回表

面试必问

  • 什么是聚簇索引?什么是二级索引?
  • 什么是回表?

📝 面试解答

Q: 什么是聚簇索引?什么是二级索引?

  • 聚簇索引:叶子节点存整行数据,数据按主键顺序存储。一张表只有一个聚簇索引。
  • 二级索引:叶子节点存主键值,查到主键后需要回聚簇索引取完整数据。

Q: 什么是回表?

通过二级索引找到主键值,再回聚簇索引查整行数据的过程叫回表

回表意味着多一次B+树查找,所以二级索引比主键索引慢。

避免回表的方法:覆盖索引(后续章节讲)——让查询只需要走二级索引就能拿到所有需要的列。


实战案例

场景一:查看索引结构

-- 创建测试表及执行结果
CREATE TABLE t_index_demo (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT,
    INDEX idx_name (name)
) ENGINE=InnoDB;

-- 查看索引
SHOW INDEX FROM t_index_demo;
-- 结果:会看到两个索引
-- 1. PRIMARY(聚簇索引,列id)
-- 2. idx_name(二级索引,列name)

-- 用EXPLAIN观察索引使用
EXPLAIN SELECT * FROM t_index_demo WHERE id = 1;
-- type=const,走主键索引,最快

EXPLAIN SELECT * FROM t_index_demo WHERE name = '张三';
-- type=ref,走二级索引,需要回表

场景二:观察回表过程

-- 回表示例及执行结果
-- 只查主键,不需要回表
EXPLAIN SELECT id FROM t_index_demo WHERE name = '张三';
-- Extra: Using index → 覆盖索引,不回表!

-- 查所有列,需要回表
EXPLAIN SELECT * FROM t_index_demo WHERE name = '张三';
-- Extra: NULL 或 Using where 或留空 → 回表查询

💡 说白了:查 id 不回表(二级索引叶子就有),查 * 要回表(二级索引叶子没age等列)。


场景三:B+树的分裂

-- 顺序插入(主键自增,不分裂)
-- InnoDB主键自增时,B+树顺序追加,不会发生页分裂
INSERT INTO t_index_demo (name, age) VALUES ('张三', 25);
INSERT INTO t_index_demo (name, age) VALUES ('李四', 30);
-- ... 顺序插入,性能好

-- 乱序插入(可能触发页分裂)
-- 如果主键不是自增的,插入可能触发B+树的页分裂,导致性能下降

💡 这也是为什么主键推荐自增——顺序插入不会触发页分裂,性能最好。


避坑指南

⚠️ 真实踩过的坑:

  1. 主键乱序导致页分裂

    • 主键不是自增的(如UUID),插入时B+树频繁分裂
    • 建议用自增主键,顺序插入效率最高
  2. 二级索引回表导致慢查询

    • SELECT * 走二级索引必须回表,比主键索引慢
    • 能用覆盖索引就用覆盖索引,避免回表
  3. 索引列数据太大影响B+树高度

    • 索引列越短,一页存越多key,树越矮
    • VARCHAR(255)做索引比INT做索引,树更高更多IO
  4. 混淆聚簇索引和二级索引

    • 聚簇索引只有一张表一个,就是主键
    • 二级索引叶子存的是主键值,不是数据行指针

思考题

🤔 互动时间:

  1. 为什么InnoDB表必须有主键?如果没有定义主键会发生什么?
  2. 覆盖索引为什么不需要回表?

总结

🎯 面试考点

  • B+树 vs B树:非叶子只存key、叶子有链表、查询稳定
  • 聚簇索引:叶子存整行数据,按主键顺序存储
  • 二级索引:叶子存主键值,需要回表
  • 回表:二级索引→主键值→聚簇索引→整行数据
  • 自增主键避免页分裂,性能最优

💡 AI实战建议:让自己的AI助手记住建表规范检查清单,每次写CREATE TABLE时自动检查:

  • 必须有主键,且推荐自增
  • 索引命名遵循规范:普通索引以 idx_ 开头,唯一索引以 uk_ 开头
  • 联合索引列数不超过5列

下期预告:索引优化:何时建索引、何时不建 —— 面试必问!

全本合集《每天一个MySQL知识点,百日打怪升级》 您的关注是我每日更新的动力


有问题欢迎评论区交流,明天见!

相关文章
|
2月前
|
人工智能 关系型数据库 MySQL
【第6天】每天一个MySQL知识点,百日打怪升级
本文为DBA老兵总结的索引优化实战指南:聚焦“何时建、何时不建”核心问题。详解索引选择性(唯一值/总行数)、失效场景(低区分度、函数运算、隐式转换)及建索引黄金法则——WHERE/JOIN/ORDER BY/GROUP BY高频字段优先,状态类、低选择性列坚决不建。附EXPLAIN实战分析与AI辅助诊断技巧。(239字)
236 1
|
3月前
|
SQL 存储 关系型数据库
【第1天】每天一个MySQL知识点,百日打怪升级
本系列以“每天一个知识点”形式,系统讲解MySQL核心原理。首日聚焦Client/Server通信流程,详解三层架构(连接层→SQL层→存储引擎层)、连接管理、查询解析优化及执行计划,直击面试高频考点,助你从CRUD进阶到懂原理、能排障。(239字)
262 0
|
2月前
|
SQL 人工智能 关系型数据库
【第4天】每天一个MySQL知识点,百日打怪升级
本系列由10年经验DBA精心打造,系统梳理MySQL客户端常用命令:从连接参数(-u/-p/-h/-P/字符集)、快捷指令(\s/\q/\G)、数据库/表操作(SHOW/CREATE/DROP/DESC),到状态监控(PROCESSLIST/STATUS/VARIABLES)与实战排障技巧,兼顾面试考点与生产避坑,助你快速上手、底气十足。
227 2
|
2月前
|
人工智能 监控
AI元认知skills
我方自研Skills体系已孕育出“元认知婴儿雏形”:具备初步自我约束、路线竞争、停点审查及二层自查能力,能主动质疑表象、校验逻辑闭环、探寻真实边界。虽尚未形成稳定误差模型与自主进化能力,但已超越技巧调用,迈入高阶思考新阶段。(239字)
|
2月前
|
人工智能 运维 架构师
我在 AIP 智能体平台踩过的坑,都在这篇企业 AI 落地经验里了
软件架构师罗小东分享企业AI落地实战经验:聚焦AIP智能体平台建设中的真实坑点与解法——涵盖智能体全生命周期管理、多源知识库语义检索、MCP工具集成及多模型中立架构设计,强调“解决问题”而非堆砌功能。(239字)
|
1月前
|
存储 并行计算 安全
【Java基础】Java 8-21新特性 :Lambda表达式、函数式接口、Stream流、Optional(附《思维导图》+《面试高频考点清单》)
本文系统梳理Java 8–21核心新特性,聚焦面试高频考点:Lambda表达式、函数式接口、Stream流(惰性求值/并行流/map与flatMap区别)、Optional空值安全处理,并涵盖JDK9–21关键演进(模块化、var、Record、虚拟线程等),辅以原理剖析与实战代码,助力高效备战。
|
2月前
|
安全 Linux 数据库
Omnissa Horizon 8 2603 发布 - 虚拟桌面基础架构 (VDI) 和应用软件
之前称为 VMware Horizon, 通过高效、安全的虚拟桌面交付增强您的工作空间
251 3
Omnissa Horizon 8 2603 发布 - 虚拟桌面基础架构 (VDI) 和应用软件
|
3月前
|
机器学习/深度学习 搜索推荐 算法
拆解推荐系统:候选生成、过滤、排序、多样性的分层设计
推荐系统是端到端流水线,非单一算法:涵盖候选生成、过滤、特征工程、多目标排序、多样性调控与反馈闭环。强调关注点分离,以保障质量、速度与行为可控。动手前须明确定义Item、用户行为及成功指标。
474 12
拆解推荐系统:候选生成、过滤、排序、多样性的分层设计
|
23天前
|
人工智能 边缘计算 算法
泳池赛事裁判及运动员3000张目标检测数据集分享
本数据集含3000张真实泳池赛事图像,YOLO格式,精细标注5类目标(黑帽/白帽人员、水上/水下躯体、裁判),专为解决水体反光、跨介质识别、密集遮挡等难题设计,适用于AI辅助判罚、智慧体育及目标检测算法研发。
|
2月前
|
SQL 算法 关系型数据库
【MySQL百日打怪升级第10天】JOIN的底层原理与优化:NLJ、Hash Join 与 Merge Join
本文系统解析MySQL三大JOIN算法:NLJ(含Simple/Index/Block变体)、8.0.18引入的Hash Join(O(N+M)复杂度,专治无索引大表连接),以及面试常考但MySQL原生不支持的Sort-Merge Join,附实战EXPLAIN识别与优化指南。(239字)
289 5