如果有人跟你谈索引, 是不是你会第一时间想到数据库, 那么索引解决了什么问题? 比如查询 SQL 慢了, 发生这种情况时, 首先要做的事情之一是查看是否慢 SQL 走了数据库索引.
在数据库中的特定表上创建索引的目的是使搜索表和查找所需行的速度更快. 可以使用数据库表的一列或多列创建索引, 方便快速随机查找和高效访问有序记录.
示例: 图书馆目录
图书馆目录是包含在图书馆中找到的书籍列表的登记册. 目录像数据库表一样组织, 通常有四列: 书名, 作者, 主题和出版日期. 通常有两种这样的目录: 一种按书名排序, 另一种按作者姓名排序. 这样的话, 你可以想一个你想读的作家, 然后翻阅他们的书, 或者找一个你知道你想读的特定书名, 以防你不知道作者的名字. 这些目录就像图书数据库的索引. 它们提供了一个排序的数据列表, 可通过相关信息轻松搜索.
简单地说, 索引是一种数据结构, 可以被视为一个目录, 将我们指向实际数据所在的位置. 因此, 当我们在表的列上创建索引时, 我们将该列和指向索引中整行的指针存储在索引中. 让我们假设一个包含书籍列表的表, 下图显示了 "Title" 列上的索引的外观:
就像传统的关系数据存储一样, 我们也可以将这个概念应用于更大的数据集. 索引的诀窍是, 我们必须仔细考虑用户将如何访问数据. 对于大小为数 TB 但有效负载非常小 (如 1KB) 的数据集, 索引是优化数据访问的必要条件. 在如此大的数据集中找到一个小的有效负载可能是一个真正的挑战, 因为我们不可能在任何合理的时间内迭代那么多的数据. 此外, 如此大的数据集很可能分布在多个物理设备上, 这意味着我们需要某种方法来找到所需数据的正确物理位置. 索引是实现这一点的最佳方法.
索引为什么会降低写性能?
索引可以极大地加快数据检索速度, 但由于额外的键, 索引本身可能很大, 这会减慢数据插入和更新的速度.
在为具有活动索引的表添加行或更新现有行时, 我们不仅要写入数据, 还要更新索引. 这将降低写入性能. 此性能降级适用于表的所有插入, 更新和删除操作. 因此, 应避免在表上添加不必要的索引, 并删除不再使用的索引. 重申一下, 添加索引是为了提高搜索查询的性能. 如果数据库的目标是提供一个经常写入而很少读取的数据存储, 那么, 降低更常见的操作 (即写入) 的性能可能不值得我们从读取中获得性能的提高. 可以参考下 Wiki 百科 https://en.wikipedia.org/wiki/Database_index 数据库索引.
题外笔者补充
谷歌系统设计指南指定了我们说的索引的好处和坏处, 那么其实深层次去思考, 索引是解决的读问题, 数据存储是解决的写问题, 而在我们设计系统, 中间件的过程中, 你会发现大量的设计都是读写分开的, 比如写磁盘是顺序写, 读磁盘是随机读. 所以是否使用索引的目的在于我们进行权衡, 索引是否对我们有帮助, 如果只有一条数据记录那么没有索引也可以. 如果数据非常庞大, 构建了很多冗余索引那么无疑是给我们写入的性能增加了难度.
参考资料
grok_system_design_interview.PDF
来源: https://www.qcloud.com/developer/article/1868408