
# 使用索引
#### 操作场景
在数据库管理中，使用索引可以显著提高查询效率。索引的使用不仅限于单个字段，还可以创建复合索引，以优化涉及多个字段的查询。
在使用索引时，应定期分析和优化索引性能。数据库管理系统通常提供工具和命令，帮助分析索引的使用情况和性能瓶颈。此外，索引的维护成本也不容忽视。插入、更新和删除操作会触发索引的更新，可能会影响性能。因此，应根据实际应用场景，合理选择索引策略，平衡查询性能和维护成本。
#### 创建索引的关键
- 避免使用没有过滤条件的聚合/查询语句。务必确保在过滤条件（比如聚合中的$match，find，update，remove语句的过滤条件）上存在对应索引。避免造成全表聚合，全表扫描等。
- 尽量使用高选择性过滤条件缩小查询范围，同时在高选择性字段上保证索引的存在。建议将索引创建限制为其中的重复值数量低于集合中总文档数的1%的字段。例如，如果您的集合包含100,000个文档，则仅在相同值出现1000次或更少的字段上创建索引。
- 多字段索引中，能缩小查询范围的高选择性字段尽量放在前面，索引效果更好。
- 有大数据量排序的业务场景，需要在sort字段结合精准匹配的过滤条件创建索引。例如：过滤条件为{a:xx, b:xx, c:xx, f:xx } 并且 sort({e:1})的业务，需要创建全覆盖索引：{a:1,b:1,c:1,f:1,e:1} ，避免产生内存排序。
- 对于同时存在精确匹配，范围匹配，排序的语句，组合索引的最佳方式：ESR原则：精确（Equal）匹配的字段放最前面，排序（Sort）条件放中间，范围（Range）匹配的字段放最后面。
- 携带collation的查询，在对应查询字段的创建索引时，也需要携带collation选项。
- 如果需要删除索引，需要确认备机无正在创建的索引（不确定可以通过使用currentOp命令进行查看当前执行中的命令）。若备机有索引正在创建，禁止立即删除索引，该操作会导致备机的删除索引操作陷入锁等待状态。
 
#### 创建索引的影响
创建索引请求下发后，会扫描当前数据的原始文档，构建索引字段与磁盘位置的映射关系数据，因此会产生IO与计算资源开销。因此：
- 当需要创建的索引涉及的数据量较多时，务必需要在业务低谷期进行创建，避免影响到生产业务。
- 当同一个集合需要创建多个索引时，使用createIndexes代替createIndex，可以在一次扫描中构建多个索引，减少创建索引带来的计算资源和IO开销。
- 核心业务表在早期需要提前规划好可能用到的索引。
 
#### 索引对数据写入的影响
虽然索引能够通过避免扫描集合中的每个文档来提高查询性能，但这种提升是有代价的。对于集合中的每个索引，每次插入、更新或删除文档时，数据库都需要更新索引并将字段写入每个索引。例如，如果一个集合有九个索引，数据库必须执行十次写入操作，才能将操作结果通知给客户端。因此，每增加一个索引都会增加写入延迟、开销和总存储空间的占用。为了获得最佳性能，建议定期审查并减少集合中不必要的索引，仅添加必要的索引来优化常用查询的性能。建议将每个集合的索引数量控制在十个以内。
