知识卡片

索引设计的实用主义原则:"覆盖80%主要查询就好,不求全"

普通读书笔记卡

内容

数据库开发规范里对索引数量给出了明确的硬性限制——单个索引字段数不超过5、单表索引数量不超过5,并明确提出一条判断标准:”建立的索引能覆盖80%主要的查询,不求全,解决问题的主要矛盾就好”。这条原则背后的现实考量是:索引是一把双刃剑,在加速读取的同时,每一个额外的索引都会给写入操作带来额外的开销(每次插入或更新数据,所有相关索引都要跟着同步维护)和额外的锁竞争,索引数量越多,写入性能的损耗就越大——文中提到见过有人给表里每个字段都建了索引,这种”追求全覆盖”的做法实际上对查询性能的提升可能非常有限,却实实在在地拖慢了每一次写入。因此索引设计不应该以”能不能覆盖所有可能出现的查询模式”为目标,而应该识别出真正高频、真正重要的那部分查询(通常是业务上最核心、访问量最大的那20%的查询模式),只为这些查询建立恰到好处的索引,至于那些低频、非核心的查询,即使暂时没有理想的索引支持、跑得慢一些,也是可以接受的代价。这条原则体现的是一种在很多资源受限、存在明确权衡的工程决策里都适用的思路:不追求覆盖100%的场景,而是精确识别出真正贡献大部分价值(或者说影响大部分体验)的那一小部分场景,把有限的资源(这里是索引数量、写入性能损耗的承受空间)集中投入到这部分,对覆盖不到的长尾场景坦然接受它们表现平庸——这本质上是帕累托法则(80/20法则)在索引设计这个具体问题上的应用。

参考来源

- 位置:《高可用架构(第1卷)》第5章《运维保障》"5.3 单表60亿记录等大数据场景的MySQL优化和运维之道"节,"5.3.2 数据库开发规范"(源文件:_epub-src/OEBPS/Text/Chapter5_3_3.xhtml) - 结论依据:原文说明"建立的索引能覆盖80%主要的查询,不求全,解决问题的主要矛盾就好……索引这个东西是一把双刃剑,在加速读的同时也引入了很多额外的写入和锁,降低了写入能力……之前看到过不少人给表里每个字段都建了索引,其实这可能对查询起不到什么作用",直接支撑本卡片结论。 - 原始内容:建立的索引能覆盖80%主要的查询,不求全,解决问题的主要矛盾就好……索引这个东西是一把双刃剑,在加速读的同时也引入了很多额外的写入和锁,降低了写入能力,这也是为什么要控制索引数的原因。