MySQL 索引:从 B+ 树底层原理到大厂高频考点全解析

⚡ 索引核心知识点全景

在深入具体面试题之前,我们先通过以下几个维度梳理 MySQL 索引的全局脉络:

1. 核心架构与原理

  • B+ 树结构:MySQL(InnoDB)默认的索引结构。设计核心是「矮胖」,通过多路平衡降低磁盘 IO 次数。
  • 叶子节点特性:所有数据存储在叶子节点,且叶子节点通过双向链表连接,天然支持范围扫描和反向遍历。
  • 非叶子节点:仅存储索引键值和指针,提高单个页的「分支因子」。

2. 存储模型

  • 聚簇索引(Clustered Index):
    • 通常是主键。
    • 索引即数据:叶子节点直接存放整行记录。
    • 唯一性:一张表只能有一个聚簇索引。
  • 非聚簇索引(二级索引):
    • 叶子节点存储 索引键值 + 主键 ID。
    • 查询非索引列时通常需要「回表」。

3. 三大优化机制

  • 覆盖索引:查询字段被索引完全覆盖,消除回表过程。
  • 最左前缀原则:联合索引的使用准则,匹配必须从最左列开始,不能跳跃。
  • 索引下推 (ICP):在存储引擎层提前过滤,大幅减少回表次数。

4. 索引设计禁忌(失效场景)

  • 违背最左匹配:跳过排在前面的列。
  • 计算/函数/转义:对索引列做运算(如 YEAR() 或 +1)。
  • 模糊通配符开头:LIKE '%abc'。
  • 隐式转换:字符串不加引号导致的类型转换。

📝 索引全量面试题集

以下内容涵盖了文档中关于索引的所有题目、详细解析及对应的大厂面试真题。

35. 🌟 索引为什么能提高 MySQL 查询效率?

索引就像一本书的目录,能让 MySQL 快速定位数据,避免全表扫描。

三分恶面渣逆袭:索引加快查询远离

它一般是 B+ 树 结构,查找效率是 $O(\log n)$,比从头到尾扫一遍数据要快得多。

MySQL 索引

除了查得快,索引还能加速排序、分组、连接等操作。

项目实践: 最常见的做法就是通过 create index 为经常用作查询条件的字段建索引,比如:

1
create index idx_name on students(name);

【面试真题库】

  1. [腾讯] QQ 后台技术一面:MySQL 索引,为什么用 B+ 树
  2. [小米] Java 后端技术一面:为什么需要索引
  3. [小公司] Java 后端面试:数据库索引讲一下,然后为什么会加快查询速度
  4. [去哪儿] 技术二面:MySQL 为什么用索引
  5. [OPPO] 面试原题:对 MySQL 索引的理解
  6. [vivo] 技术一面:索引,为什么使用索引更快
  7. [腾讯] 云后台技术一面:介绍下索引?底层是啥?

36. 🌟 能简单说一下索引的分类吗?

二哥的 Java 进阶之路:索引类型

  1. 按功能分类:主键索引、唯一索引、全文索引。
  2. 按数据结构分类:B+ 树索引、哈希索引。
  3. 按存储内容分类:聚簇索引、非聚簇索引。

(1) 主键索引

主键索引用于唯一标识表中的每条记录,其列值必须唯一且非空。

processon:主键索引

如果在创建表的时候没有指定主键,InnoDB 会优先选择一个非空的唯一索引作为主键;如果没有,则自动生成一个隐藏的 _rowid。

(2) 唯一索引 vs 主键索引

  • 主键索引:唯一 + 非空。一个表只能有一个。
  • 唯一索引:值必须唯一,但允许插入多个 NULL 值。一个表可以有多个。

(3) 普通索引 vs 唯一索引

  • 普通索引:仅用于加速查询,不限制唯一性。
  • 唯一索引:强制唯一,插入或更新时会检查约束。

(4) 全文索引

适用于 CHAR、VARCHAR 和 TEXT 字段,优化长文本检索。

  • MySQL 5.7+ 内置 ngram 解析器处理中、日、韩分词。
  • 使用 MATCH...AGAINST 进行检索,性能远高于 LIKE '%keyword%'。

【面试真题库】

  1. [科大讯飞] 非凡计划:聊聊 MySQL 的索引
  2. [腾讯] QQ 后台:MySQL 索引,为什么用 B+ 树
  3. [携程] 暑期实习一面:讲一讲 MySQL 的索引
  4. [阿里妈妈] 技术一面:索引的分类,创建索引的最佳实践
  5. [360] 技术一面:MySQL 的索引用过哪些
  6. [用友] 面试原题:索引是什么?有哪些索引
  7. [作业帮] Java 后端一面:普通索引的叶子节点存储的是什么
  8. [作业帮] Java 后端一面:InnoDB 底层有哪些数据结构
  9. [比亚迪] 技术面试:索引有哪些,区别是什么

37. 🌟 创建索引有哪些注意点?

  1. 选择合适的字段:
    • 频繁出现在 WHERE、JOIN、ORDER BY 里的字段。
    • 区分度要高(如用户 ID、手机号),避免性别等低区分度字段。
  2. 控制数量:避免过度索引。单表建议不超过 5 个,过多的索引会显著降低写操作性能。
  3. 遵循最左前缀:联合索引设计时,区分度最高的放在最左侧。
  4. 等值优先:等值查询在范围查询之前。

【面试真题库】

  1. [用友金融] 一面:索引的作用,加索引需要注意什么
  2. [京东] 后端实习:查询和更新都频繁的字段是否适合创建索引
  3. [小米] 春招一面:索引怎么设计才是最好的
  4. [京东] 技术一面:MySQL 索引结构,建立索引的策略
  5. [阿里妈妈] 技术一面:创建索引的最佳实践
  6. [OPPO] 秋招一面:建索引的时候应该注意什么
  7. [京东] 技术一面:建立索引考虑哪些问题

38. 🌟 索引哪些情况下会失效呢?

  1. 左模糊查询:LIKE '%xxx' 会失效。
  2. 列参与运算/函数:WHERE YEAR(date) = 2023 失效;WHERE id + 1 = 10 失效。
  3. 违背最左前缀原则:跳过联合索引的第一列。
  4. OR 连接非索引列:WHERE id = 1 OR age = 20 (age 无索引) 会导致 id 索引也失效。
  5. 不等于查询:!= 或 <> 有时会导致全表扫描。

【面试真题库】

  1. [字节跳动] 技术一面:where b=5 是否一定会命中索引?(失效场景)
  2. [京东] 技术一面:索引失效的情况
  3. [比亚迪] 技术面试:索引失效场景
  4. [OPPO] 面试原题:什么情况下索引失效?
  5. [理想汽车] 一面:什么操作会导致索引失效?

39. 索引不适合哪些场景呢?

  1. 数据量太小:数据量小于 1000 行,全表扫描可能比索引查完再回表更快。
  2. 区分度极低的列:如「性别」字段。
  3. 频繁更新的列:每次更新都要维护 B+ 树。
  4. 由于 TEXT/BLOB 等大字段。

什么是区分度? 公式:COUNT(DISTINCT column) / COUNT(*)。越接近 1 越适合索引。

【面试真题库】

  1. [字节跳动] 二面:性别字段要建立索引吗?什么是区分度?
  2. [快手] 一面:什么样的字段适合加索引?什么不适合?

40. 索引优化的思路?

  1. 慢日志:定位 SQL 瓶颈。
  2. EXPLAIN 分析:查看执行计划,重点看 type、key 和 Extra。
  3. 精简索引:合并冗余索引,利用联合索引代替多个单列索引。
  4. 利用覆盖索引:让索引包含所有返回字段。

【面试真题库】

  1. [比亚迪] 技术面试:索引优化的思路

41. 🌟 为什么 InnoDB 要使用 B+ 树作为索引?

核心三点:

  1. 更矮胖:相比二叉树,B+ 树分支因子极大(16KB/页),3 层就能存 2000 万数据。IO 次数少。
  2. 范围查询:叶子节点通过双向链表相连,极其适合 BETWEEN、ORDER BY 操作。B 树不支持如此高效的范围扫描。
  3. 稳定性:所有查询必须到叶子节点,查询耗时稳定。

William Johnson:b+树

B+ 树 vs B 树、Hash、红黑树

  • vs Hash:Hash 不支持范围查询和排序。
  • vs B 树:B 树非叶子节点也存数据,导致层数变高,且不支持链表顺序扫。
  • vs 二叉树:层级太深,IO 寻址次数过多。

【面试真题库】

  1. [字节跳动] 说说 B+ 树,为什么 3 层能存 2000 万?
  2. [腾讯] 为什么选用 B+ 树?
  3. [小米] 说一说 MySQL 索引的底层机制
  4. [得物] MongoDB 为什么用 B 树,MySQL 为何用 B+ 树?
  5. [百度] B+ 树叶子是单向还是双向链表?大值向小值检索怎么做?

42. 🌟 一棵 B+ 树能存储多少条数据呢?

答案:约 2000 万条。

计算推导:

  • InnoDB 页默认 16KB。
  • 非叶子节点:存 (主键 ID + 指针)。主键 8B + 指针 6B = 14B。一个页能存 $16384 / 14 \approx 1170$ 个指针。
  • 叶子节点:存行数据。假设一行 1KB,一个页存 16 条。
  • 三层容量:$1170 \times 1170 \times 16 \approx 21,902,400$。

计算公式演示

【面试真题库】

  1. [奇安信] 2KW 数据,B+ 树高度几层?(3层)
  2. [美团] 一张表最多存多少数据?(常答 2KW,基于 3 层树计算)
  3. [腾讯] 叶子节点能存多少条数据?(取决于行大小,一般 1KB 存 16 条)

43-44. B+ 树 vs B 树 vs 跳表

(1) B+ 树 vs B 树(图书馆类比)

  • B 树:像普通图书馆,每一层书架都有书。层级深(树高),找书要爬上爬下。
  • B+ 树:索引层只有目录(矮胖),书全在底层逻辑连接。

(2) B+ 树 vs 跳表(登山缆车类比)

  • 跳表:像缆车,每层都是指针。存 2000 万数据要 20 层,导致 20 次随机磁盘 IO。
  • B+ 树:只要 3 次 IO。跳表适合内存(如 Redis),B+ 树才是磁盘王者。

【面试真题库】

  1. [贝壳找房] 为什么用 B+ 树不用 B 树?
  2. [饿了么] 索引为什么用 B+ 树不用跳表?时间复杂度对比?

45. B+ 树索引和 Hash 索引的区别?

  • Hash 索引:等值查找 $O(1)$。但不支持范围、排序、模糊匹配、最左匹配。
  • B+ 树索引:支持 $O(\log N)$ 查找及所有高级用法。

46. 🌟 聚簇索引和非聚簇索引的区别?

  • 聚簇索引:叶子节点存 完整数据行。一张表只有一个。
  • 非聚簇索引:叶子节点存 主键 ID。查询时常涉及「回表」。

聚簇 vs 非聚簇

【面试真题库】

  1. [支付宝] 聚簇索引和非聚簇索引的区别?
  2. [快手] 区别是什么?
  3. [腾讯] 索引怎么存的?每个索引一个 B+ 树吗?

47. 🌟 回表了解吗?

定义:通过二级索引查到主键,再通过主键查聚簇索引获取全行数据的过程。

了解 MRR 吗? MRR (Multi-Range Read) 会将主键列表排序后再按序回表,将 随机 IO 转为顺序 IO。


48-50. 联合索引与最左前缀原则

(1) 联合索引结构

联合索引 (A, B, C) 在 B+ 树中按字段顺序排列。

(2) 最左前缀原则

必须从最左列开始。如 (A, B, C):

  • WHERE A=1 AND B=2:匹配。
  • WHERE B=2:失效。
  • WHERE A=1 AND C=3:A 匹配,C 丢弃(无法定位)。

【面试真题库】

  1. [百度] 联合索引底层存储结构?
  2. [美团] 覆盖索引,回表过程?
  3. [字节跳动] (a,b,c) 联合索引,select * where a=1 and b in (1,2) and c>3 走索引吗?(走)

51. 🌟 什么是索引下推 (ICP)?

定义:在索引扫描过程中,服务器将部分 WHERE 条件过滤操作推送到存储引擎。

  • 效果:减少回表次数。原本需要回表判断的条件,在索引层直接踢掉。

索引下推图解


52. 如何查看是否用到了索引?

使用 EXPLAIN。

  • key 列显示实际用的索引。
  • Extra 显示 Using index condition 说明命中索引下推。

场景实操:联合索引 abc

  • a=1, c=1:命中 a 索引(ICP 过滤 c)。
  • b=1, c=1:全表扫描。
  • a=1, c=1, b=1:命中全索引(优化器重排)。

💡 总结建议: 大厂面试官最爱问 “为什么”。不要只背结论,要推导过程:

  1. B+ 树更矮胖 $\rightarrow$ 减少随机磁盘 IO。
  2. 指针 + 键值 $\rightarrow$ 提高页的存储效率 $\rightarrow$ 增加分支因子。
  3. 最左匹配 $\rightarrow$ 因为 B+ 树在构建索引键时是按字段顺序全局排序的。