【计算机基础速成】第三课:索引入门与高频面试题

4 小时前(已编辑)

【计算机基础速成】第三课:索引入门与高频面试题

1. 这节课的目标

索引是数据库面试中的超级高频题。

很多面试官会直接问:

  • 什么是索引?
  • 索引为什么能提高查询效率?
  • MySQL 索引底层为什么用 B+ 树?
  • 什么是聚簇索引、非聚簇索引?
  • 索引是不是越多越好?
  • 什么情况下索引会失效?

这节课学完后,你至少要做到:

  • 能说清楚索引的作用
  • 能用“减少全表扫描”解释索引为什么快
  • 能知道 B+ 树是高频标准答案
  • 能知道主键索引和二级索引的基本区别
  • 能回答几个常见索引失效场景

2. 什么是索引

一句话理解

索引就是帮助数据库更快查找数据的数据结构。

更通俗一点

它有点像一本书前面的目录。

如果一本书没有目录,你要找某一章内容,就只能一页一页翻。 如果有目录,你可以先定位大概位置,再快速找到目标内容。

数据库里的索引也是类似的作用。

Mermaid Loading...

3. 面试怎么回答“什么是索引”

标准回答

索引是数据库中一种用于提高查询效率的数据结构。它可以帮助数据库快速定位到满足条件的数据,减少全表扫描的次数,从而提高查询性能。

关键词

  • 数据结构
  • 提高查询效率
  • 快速定位数据
  • 减少全表扫描

这四个关键词你一定要记住。


4. 为什么索引能加快查询

4.1 没有索引会发生什么

假设有一张用户表,里面有 100 万条数据。

你执行:

select * from user where id = 10086;

如果 id 上没有索引,数据库可能需要从头到尾一条条找,这就叫:

全表扫描

数据量一大,查询就会变慢。


4.2 有索引会发生什么

如果 id 上建立了索引,数据库就可以借助这个索引快速定位到目标记录,而不需要遍历全部数据。

所以索引为什么快,核心原因就是:

它减少了扫描的数据量,降低了查找成本。


4.3 面试标准答法

索引之所以能提高查询效率,是因为它维护了一套额外的数据结构,能够帮助数据库快速定位目标数据,避免每次查询都做全表扫描。尤其是在数据量比较大的情况下,索引带来的性能提升会非常明显。


5. 索引的代价是什么

面试官有时候不会只听你说优点,还会追问:

索引是不是越多越好?

答案当然不是。

索引的代价

  • 索引要占用额外存储空间
  • 插入、删除、更新数据时,索引也要一起维护
  • 索引太多会影响写入性能
  • 不合理的索引可能还会让优化器选择变复杂

面试标准答法

索引不是越多越好。虽然索引可以提升查询性能,但它也会占用额外空间,并增加增删改时的维护成本,所以索引应该根据查询场景合理设计。


6. MySQL 索引底层为什么常说是 B+ 树

这是索引面试中的核心题。

你现在不需要学得像数据库内核工程师那么深,但一定要掌握标准答法。

Mermaid Loading...

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. 聚簇索引和非聚簇索引

这个概念对初学者容易绕,但你不需要一次学得太深。

先掌握最小可答版本。

Mermaid Loading...

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';

查询需要的字段 nameage 都在索引里,数据库可以直接从索引中返回结果,这就属于覆盖索引。

好处

  • 减少回表
  • 提升查询效率

面试答法

覆盖索引指的是查询所需的字段都可以直接从索引中获取,不需要再回表查询原表数据,因此通常能够进一步提升查询性能。


10. 联合索引与最左前缀匹配

这是实习面试很爱问的一组内容。

Mermaid Loading...

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 = 20
  • where name = 'Tom' and age = 20 and city = 'Beijing'

而下面这种通常不行或效果不好:

  • where age = 20
  • where city = 'Beijing'

因为跳过了最左边的 name

面试标准答法

联合索引通常遵循最左前缀匹配原则,也就是查询条件需要从索引最左侧字段开始连续匹配。如果跳过最左字段,索引往往无法被充分利用。


11. 索引失效的常见场景

这个部分非常关键,因为面试官很喜欢问:

什么情况下索引会失效?

你不用追求全背全会,但要掌握几个最典型的场景。

Mermaid Loading...

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 口头复述题

请你尝试不看讲义回答:

  1. 什么是索引?
  2. 索引为什么能提高查询效率?
  3. 为什么 MySQL 索引底层常用 B+ 树?
  4. 什么是聚簇索引和非聚簇索引?
  5. 什么是回表和覆盖索引?
  6. 什么是最左前缀匹配?
  7. 常见的索引失效场景有哪些?

18.2 思考题

  1. 为什么性别字段通常不适合单独建立索引?
  2. 为什么索引不是越多越好?
  3. 为什么 like '%abc' 可能导致索引效果不好?

18.3 今日最低完成标准

如果今天时间紧,至少完成下面任务:

  1. 背会本课 6 张最小记忆卡片
  2. 能口头回答 7 道高频题
  3. 能完整复述一次“你说一下数据库索引”

19. 下一课预告

第四课:事务、ACID 与隔离级别

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...