【计算机基础速成】第三课:索引入门与高频面试题
1. 这节课的目标
索引是数据库面试中的超级高频题。
很多面试官会直接问:
- 什么是索引?
- 索引为什么能提高查询效率?
- MySQL 索引底层为什么用 B+ 树?
- 什么是聚簇索引、非聚簇索引?
- 索引是不是越多越好?
- 什么情况下索引会失效?
这节课学完后,你至少要做到:
- 能说清楚索引的作用
- 能用“减少全表扫描”解释索引为什么快
- 能知道 B+ 树是高频标准答案
- 能知道主键索引和二级索引的基本区别
- 能回答几个常见索引失效场景
2. 什么是索引
一句话理解
索引就是帮助数据库更快查找数据的数据结构。
更通俗一点
它有点像一本书前面的目录。
如果一本书没有目录,你要找某一章内容,就只能一页一页翻。 如果有目录,你可以先定位大概位置,再快速找到目标内容。
数据库里的索引也是类似的作用。
3. 面试怎么回答“什么是索引”
标准回答
索引是数据库中一种用于提高查询效率的数据结构。它可以帮助数据库快速定位到满足条件的数据,减少全表扫描的次数,从而提高查询性能。
关键词
- 数据结构
- 提高查询效率
- 快速定位数据
- 减少全表扫描
这四个关键词你一定要记住。
4. 为什么索引能加快查询
4.1 没有索引会发生什么
假设有一张用户表,里面有 100 万条数据。
你执行:
select * from user where id = 10086;如果 id 上没有索引,数据库可能需要从头到尾一条条找,这就叫:
全表扫描
数据量一大,查询就会变慢。
4.2 有索引会发生什么
如果 id 上建立了索引,数据库就可以借助这个索引快速定位到目标记录,而不需要遍历全部数据。
所以索引为什么快,核心原因就是:
它减少了扫描的数据量,降低了查找成本。
4.3 面试标准答法
索引之所以能提高查询效率,是因为它维护了一套额外的数据结构,能够帮助数据库快速定位目标数据,避免每次查询都做全表扫描。尤其是在数据量比较大的情况下,索引带来的性能提升会非常明显。
5. 索引的代价是什么
面试官有时候不会只听你说优点,还会追问:
索引是不是越多越好?
答案当然不是。
索引的代价
- 索引要占用额外存储空间
- 插入、删除、更新数据时,索引也要一起维护
- 索引太多会影响写入性能
- 不合理的索引可能还会让优化器选择变复杂
面试标准答法
索引不是越多越好。虽然索引可以提升查询性能,但它也会占用额外空间,并增加增删改时的维护成本,所以索引应该根据查询场景合理设计。
6. MySQL 索引底层为什么常说是 B+ 树
这是索引面试中的核心题。
你现在不需要学得像数据库内核工程师那么深,但一定要掌握标准答法。
6.1 先记住结论
MySQL 中常见的索引结构,尤其是 InnoDB 的索引,底层通常采用 B+ 树。
6.2 为什么不是普通二叉树
原因 1:可能退化
普通二叉树在极端情况下可能退化成链表,查询效率会变差。
原因 2:树太高
数据库数据量很大,如果树高度太高,就意味着磁盘 IO 次数会变多,性能会差。
6.3 为什么 B+ 树更适合数据库索引
原因 1:层数低,磁盘 IO 少
B+ 树是多叉平衡树,一个节点可以存很多键值,所以树的高度更低。 树越矮,查询时访问的磁盘页就越少。
原因 2:范围查询更强
B+ 树的叶子节点通常按顺序连接,适合范围查询,比如:
select * from user where id between 100 and 200;原因 3:查询更稳定
B+ 树的非叶子节点主要用于索引导航,真正的数据通常集中在叶子节点,查询路径更稳定。
6.4 面试标准答法
MySQL 常见索引底层采用 B+ 树,主要原因是 B+ 树是多路平衡查找树,树高更低,可以减少磁盘 IO;同时叶子节点按顺序连接,范围查询效率更高,所以它比普通二叉树、更适合作为数据库索引结构。
7. 聚簇索引和非聚簇索引
这个概念对初学者容易绕,但你不需要一次学得太深。
先掌握最小可答版本。
7.1 聚簇索引
一句话理解
数据本身就和索引放在一起。
更容易理解的说法
InnoDB 里,主键索引通常就是聚簇索引。表中的数据记录本身是按主键索引的方式组织存储的。
也就是说:
- 主键索引的叶子节点里,存的就是完整数据
面试答法
聚簇索引指的是数据行本身和索引组织在一起,InnoDB 中主键索引通常采用聚簇索引结构,叶子节点存储的是完整的行数据。
7.2 非聚簇索引
一句话理解
索引和真实数据是分开的。
在 InnoDB 中,普通索引也常叫二级索引。
它的叶子节点里通常不是完整数据,而是:
- 索引列值
- 对应主键值
然后再根据主键值去主键索引里找完整数据。
这个过程常被称为:
回表
面试答法
非聚簇索引通常不会直接在叶子节点中存完整行数据,而是存储索引列以及对应的主键值。查询时如果需要其他字段,往往还需要根据主键再查一次聚簇索引,这个过程通常叫回表。
8. 什么是回表
一句话理解
先通过二级索引找到主键,再通过主键去聚簇索引中找完整数据。
举例
假设有索引:
index idx_name(name)你执行:
select * from user where name = 'Tom';数据库可能先从 idx_name 找到对应记录的主键值,然后再去主键索引里找到整行数据。
这就是回表。
9. 覆盖索引
这也是很常见的追问点。
一句话理解
查询需要的字段,刚好在索引里就能拿到,不需要再回表。
示例
假设有联合索引:
index idx_name_age(name, age)如果执行:
select name, age from user where name = 'Tom';查询需要的字段 name 和 age 都在索引里,数据库可以直接从索引中返回结果,这就属于覆盖索引。
好处
- 减少回表
- 提升查询效率
面试答法
覆盖索引指的是查询所需的字段都可以直接从索引中获取,不需要再回表查询原表数据,因此通常能够进一步提升查询性能。
10. 联合索引与最左前缀匹配
这是实习面试很爱问的一组内容。
10.1 什么是联合索引
一句话理解
把多个字段放在一个索引里。
例如:
index idx_name_age_city(name, age, city)这就是一个按照 name -> age -> city 顺序建立的联合索引。
10.2 什么是最左前缀匹配
一句话理解
联合索引从最左边的字段开始匹配,不能跳着用。
比如有联合索引:
index idx_name_age_city(name, age, city)下面这些通常可以利用索引:
where name = 'Tom'where name = 'Tom' and age = 20where name = 'Tom' and age = 20 and city = 'Beijing'
而下面这种通常不行或效果不好:
where age = 20where city = 'Beijing'
因为跳过了最左边的 name。
面试标准答法
联合索引通常遵循最左前缀匹配原则,也就是查询条件需要从索引最左侧字段开始连续匹配。如果跳过最左字段,索引往往无法被充分利用。
11. 索引失效的常见场景
这个部分非常关键,因为面试官很喜欢问:
什么情况下索引会失效?
你不用追求全背全会,但要掌握几个最典型的场景。
11.1 对索引列做函数、计算、表达式操作
例如:
select * from user where year(create_time) = 2024;如果 create_time 上有索引,这种写法也可能导致索引无法正常利用。
为什么
因为数据库很难直接利用原始索引结构。
11.2 使用 %abc 这种前置模糊查询
例如:
select * from user where name like '%om';这种前面带 % 的写法,通常不利于索引使用。
但:
select * from user where name like 'Tom%';这种从左往右匹配的情况通常更容易利用索引。
11.3 联合索引不满足最左前缀
例如联合索引是:
index idx_name_age(name, age)如果你只查:
where age = 20就可能无法很好利用这个联合索引。
11.4 数据区分度太低
如果某个字段重复值特别多,比如性别字段只有:
- 男
- 女
即使建立索引,优化器也可能觉得走索引意义不大,最后选择全表扫描。
11.5 使用不合适的类型转换
例如字段本来是字符串,你却拿数字去比,可能触发隐式类型转换,影响索引使用。
12. 面试里怎么回答“索引失效”
标准回答
常见的索引失效场景包括:对索引列做函数或表达式操作、使用前置模糊匹配、联合索引没有满足最左前缀原则、字段区分度过低,以及一些不合理的隐式类型转换等。
如果你时间紧,就把这句话背下来。
13. 什么情况下适合建索引
适合建索引的场景
- 经常作为查询条件的字段
- 经常用于排序、分组的字段
- 经常用于连接查询的字段
- 区分度较高的字段
不太适合建索引的场景
- 很少查询的字段
- 经常更新且查询价值不高的字段
- 区分度很低的字段
面试答法
索引更适合建立在高频查询、排序、分组、连接使用的字段上,尤其是区分度较高的字段;而对于更新频繁且查询价值不高、或者重复值很多的字段,通常不建议随意建立索引。
14. 索引是不是越多越好
标准回答
索引不是越多越好。索引虽然能提升查询效率,但会占用额外存储空间,还会增加插入、更新、删除操作时的维护成本,所以索引设计要结合业务查询场景权衡。
15. 一套面试可直接复述的完整答法
如果面试官问:
你说一下数据库索引。
你可以这样回答:
索引本质上是数据库中用于提高查询效率的一种数据结构,
它可以帮助数据库快速定位目标数据,减少全表扫描。
MySQL 中常见索引底层会使用 B+ 树,因为它树高更低、磁盘 IO 更少,
而且范围查询效率比较高。
在 InnoDB 中,主键索引通常是聚簇索引,叶子节点存完整数据;
普通索引通常是二级索引,可能需要回表。
另外索引也不是越多越好,因为它会占用空间,并增加增删改时的维护成本。
常见索引失效场景包括对索引列做函数操作、前置模糊查询、联合索引不满足最左前缀等。这段答法你如果能顺利说出来,数据库面试已经不像“零基础选手”了。
16. 本课高频面试题
16.1 什么是索引
标准回答
索引是数据库中用于提高查询效率的一种数据结构,它能够帮助数据库快速定位目标数据,减少全表扫描。
16.2 索引为什么能提高查询效率
标准回答
因为索引维护了额外的数据结构,能够帮助数据库更快定位到目标记录,避免每次查询都扫描整张表,从而降低查找成本。
16.3 为什么 MySQL 索引底层常用 B+ 树
标准回答
B+ 树是多路平衡查找树,树高更低,可以减少磁盘 IO;同时叶子节点按顺序连接,更适合范围查询,因此非常适合作为数据库索引结构。
16.4 什么是聚簇索引和非聚簇索引
标准回答
聚簇索引中数据行和索引组织在一起,InnoDB 中主键索引通常就是聚簇索引,叶子节点存储完整行数据;非聚簇索引通常只存索引列和主键值,查询完整数据时可能需要回表。
16.5 什么是回表
标准回答
回表是指先通过二级索引找到对应主键值,再根据主键去聚簇索引中查询完整行数据的过程。
16.6 什么是覆盖索引
标准回答
覆盖索引是指查询所需字段都已经包含在索引中,可以直接从索引返回结果,不需要再回表,因此通常效率更高。
16.7 什么是最左前缀匹配
标准回答
联合索引通常遵循最左前缀匹配原则,也就是查询条件需要从联合索引最左边的字段开始连续匹配,跳过最左字段时通常无法充分利用索引。
16.8 什么情况下索引会失效
标准回答
常见索引失效场景包括对索引列做函数或表达式操作、前置模糊匹配、联合索引不满足最左前缀原则、字段区分度过低以及不合理的隐式类型转换等。
17. 本课最小记忆卡片
卡片 1
- 索引:提高查询效率的数据结构
- 核心作用:减少全表扫描
卡片 2
- B+ 树:树高低、IO 少、范围查询强
卡片 3
- 聚簇索引:叶子节点存完整数据
- 二级索引:可能要回表
卡片 4
- 覆盖索引:查询字段都在索引里,不用回表
卡片 5
- 联合索引:多个字段组成一个索引
- 最左前缀:从最左边开始连续匹配
卡片 6
- 索引失效:函数操作、前置
%、跳过最左列、区分度低、隐式转换
18. 课后练习
18.1 口头复述题
请你尝试不看讲义回答:
- 什么是索引?
- 索引为什么能提高查询效率?
- 为什么 MySQL 索引底层常用 B+ 树?
- 什么是聚簇索引和非聚簇索引?
- 什么是回表和覆盖索引?
- 什么是最左前缀匹配?
- 常见的索引失效场景有哪些?
18.2 思考题
- 为什么性别字段通常不适合单独建立索引?
- 为什么索引不是越多越好?
- 为什么
like '%abc'可能导致索引效果不好?
18.3 今日最低完成标准
如果今天时间紧,至少完成下面任务:
- 背会本课 6 张最小记忆卡片
- 能口头回答 7 道高频题
- 能完整复述一次“你说一下数据库索引”
19. 下一课预告
第四课:事务、ACID 与隔离级别