如果你曾查询过一个数据库,那么即使你当时没有意识到,也很可能已经使用过索引了。数据库索引用于通过创建辅助数据结构来加速读取查询,使扫描更快。本文将详细介绍数据库索引的工作原理,并特别关注 MySQL,这款深受许多人喜爱的数据库软件。


索引加速查询

索引本质上是一种加速读取查询的方式,尤其是带有过滤条件(例如 WHERE)的查询。它是数据库引擎中一种存在于关联表之外的额外数据结构,指向你尝试查询的数据。
为了避免常见的图书馆类比,我们假设一个极端的场景:你在 MySQL 数据库中有一个包含所有用户的表。你正在为你的社交应用添加功能,使用户可以搜索和过滤其他用户,这意味着将有查询在生产环境中运行,扫描整个用户表。更糟的是,你的应用相当成功,用户达到了几十万量级!
然而,不幸的是,现在对用户表进行 SELECT 操作性能不是很好。基于 UI 输入应用的过滤条件(如用户所在位置、账户类型、最近活动时间等数据库中的列),需要扫描整个用户表,平均得耗时 O(N/2)。你的查询需要5-6秒才能运行完毕,这对于内部数据分析可能还算可接受,但远远不能满足顺滑的用户体验需求。
为了解决这个问题,你可以在用户表的“最近活动时间(most recent activity)”列上创建一个索引(通过 CREATE INDEX )。在后台,MySQL 会创建一个新的伪“表”,其中包含了两个列:一个是“最近活动时间”的值,一个是指向用户表中记录的指针。神奇之处在于,这个“表”会被排序并存储为二叉树,按“最近活动时间”列的值排序。结果是,查询效率提高到了 O(Log(n)),运行时间仅需一秒或更短。
这就是索引的基本原理。如果你知道将会反复运行特定的查询,并且担心读取性能,那么创建一个(或几个)索引可以显著提升查询速度。
不过这只是简单版本。在幕后还发生了很多其他操作,而索引过多可能甚至会降低查询性能。


数据库索引的幕后工作原理

索引并不是魔法,它是一种包含指向特定数据库记录的指针的数据结构。在没有索引的情况下,数据库中的数据通常以堆形式存储,基本上是一堆无序的行。这实际上可以在微软 SQL Server 和 Azure SQL 数据库中设置和切换。
在实际操作中,数据很少是完全没有排序的。通常,你会使用某种主键(Primary Key)进行排序——在 MySQL 中,主键可以与索引相同。例如,使用一个自动递增的整数作为主键。但数据当然只能按一个列排序,这会限制排序的“二叉效率”,只能针对你查询过滤的那个单一的、有序的列。索引基本上是一种让表可以按多列排序的方式,从而获得多列上过滤的二叉搜索效率。
当你在某个列上创建索引时,其实是在创建一个包含两列的新表:一个是被索引列的值,另一个是指向记录存储位置的指针。虽然索引的长度与原表相同,但宽度可能会显著变短,因此需要更少的磁盘块进行存储和遍历。MySQL 中的指针通常很小,通常少于 5 字节。著名的 Stack Overflow帖子 提供了详细的存储块数计算,对于更深入了解此原理的人可能会有帮助。
如果你未创建任何索引,那么当前的数据库中可能已经由系统生成了一些索引。你可以通过以下命令查看特定表上的索引:

SHOW INDEX FROM table_name FROM db_name;

此外,运行 EXPLAIN 语句时,也可以看到查询计划中用到的索引信息。这是 MySQL 文档中可能的 EXPLAIN 输出值的表格:注意 possible_keyskey 两列,均与索引选择有关。

ColumnJSON nameDefinition
idselect_idThe SELECT identifier
select_typeNoneThe SELECT type
tabletable_nameThe table for the output row
partitionspartitionsThe matching partitions
typeaccess_typeThe join type
possible_keyspossible_keysThe possible indexes to choose
keykeyThe index actually chosen
key_lenkey_lengthThe length of the chosen key
refrefThe columns compared to the index
rowsrowsEstimate of rows to be examined
filteredfilteredPercentage of rows filtered by table condition
ExtraNoneAdditional information

这种 EXPLAIN 的使用方式在创建索引时也很有帮助,可以用于调试验证新索引是否按预期工作。


索引的类型

我们主要讨论了唯一索引(Unique Index),但它实际上只是众多类型中的一种。以下是一些常见的索引类型:

唯一索引(Unique Index)

唯一索引保证列中没有两个相同的非空值,同时对列进行排序,使查询可以利用二叉搜索实现 O(Log(n)) 效率。另外,主键(Primary Key)也是一种特殊的唯一索引。

文本索引(Text Index)

使用 FULLTEXT 创建文本索引,适用于 MySQL 的 CHARVARCHARTEXT 数据类型。MySQL 的文本索引提供了类似现代文本解析功能,包括自然语言搜索、布尔搜索,以及查询扩展搜索。


MySQL 中创建索引

创建索引的语法非常标准,例如:

CREATE INDEX index_name ON table_name (column_name);

以下是自定义索引的选项和示例:

CREATE INDEX users_most_recent_activity ON users ({most_recent_activity} DESC) COMMENT 'for querying by most recent activity';

你可以自定义索引类型、排序方式、算法以及锁定策略等。更多内容可参考 MySQL 文档中关于索引的章节。



数据库索引是如何工作的?插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:http://choupangxia.cn/2025/09/07/how-do-database-indexes-work/