# 21. 索引

当索引被应用于数据库时，索引成为一个著名的概念。或早或晚，数据库性能不再令人满意。最先需要考虑的事情之一是数据库索引。

在数据库中的特定表上创建索引的目标是更快地在表中搜索并找到我们需要的一行或多行。创建索引的方式可以是使用数据库表中的一列或多列，提供快速随机查找和高效访问有序的记录。

## 1. 图书馆目录

图书馆目录是一张包含图书馆中的书的登记表。目录的组织形式如同数据库表，一般包含四列：书名、作者、主题和出版日期。通常有两种这样的目录：一种根据书名排序，另一种根据作者名排序。按照这种方式，你可以想好要阅读哪个作者的书然后查看该作者的书，或者可以在不知道作者名的情况下查找想阅读的特定书的书名。这些目录如同书的数据库中的索引。它们提供数据的有序列表，可以根据相关信息方便地搜索。

简而言之，索引是一种类似于目录表的数据结构，指向数据实际存储的位置。因此当我们在表的一列上创建索引时，我们在索引中存储这一列以及指向整行的指针。假设表中包含书的列表，下图为「书名（Title）」列上的索引的示意图：

![](https://github.com/wat1r/Grokking-System-Design/blob/main/ch21_1.png)

如同传统关系型数据库的存储，我们也可以将这个概念应用于更大的数据库。使用索引时需要注意的是，我们必须仔细考虑用户将如何访问数据。当数据集的大小有好几万亿字节，但是负载量很小（例如 1 KB）时，索引用于优化数据访问是非常重要的。在如此大的数据集当中寻找一个小的负载是非常困难的，因为我们不可能在任何合理的时间内遍历如此多的数据。另外，如此大的数据集非常有可能分布在多台物理设备上——这意味着我们需要一些方法找到预期数据的正确物理位置。索引是实现这一点的最好方法。

## 2. 索引如何降低写操作的性能？

索引可以显著提升数据检索的速度，但是其自身可能因为额外的键导致占用很大空间，降低插入和更新数据的速度。

当向一个有活跃索引的表中添加行或者更新数据时，我们不只是需要写数据，还需要更新索引。这会降低写操作的性能。这张表的所有插入、更新和删除操作的性能都会降低。因为这个原因，应该避免在表上添加不必要的索引，不再使用的索引应该被移除。重申一遍，添加索引是为了提升搜索的性能。如果数据库的目标是提供一个写操作多、读操作少的数据存储，这种情况下为了提升写操作的性能而降低更常见的写操作的性能是不值得的。

更多信息请查看[数据库索引](https://en.wikipedia.org/wiki/Database_index)。
