MongoDB中的索引
在任何数据库中,可以用索引支持高效执行查询。如果没有索引,数据库必须扫描集合或表中的每个文档,才能选择与查询语句匹配的文档。如果查询存在适当的索引,数据库可以使用索引来限制必须检查的文档数量,从而提升查询效率。索引的使用可以大大减少查询所需的时间和资源,让数据库能更快速地找到所需数据。因此,在设计数据库时,充分考虑并优化索引的使用,是提升数据库性能的关键一步。
MongoDB提供了丰富的索引类型和功能,并具有针对语言的排序顺序,以支持对数据的复杂访问模式。MongoDB索引可以根据应用程序的需求和查询模式随时创建和删除,并且可以声明在文档中的任何字段上,包括嵌套在数组中的字段。这些灵活的索引功能使得在MongoDB中进行高效的数据访问变得更加简单和便捷。无论是针对特定的字段还是针对文档中的嵌套字段,都可以根据实际需求来创建索引,以提升查询性能和响应时间。通过合理设计和使用索引,可以最大限度地优化MongoDB的性能,提供更好的数据访问体验。
因此,让我们讨论如何在MongoDB中最好地使用索引。
使用复合索引
复合索引是由几个不同字段组成的索引。例如,如果您对“姓氏”和“名字”都进行查询,通常最高效的做法是创建包含“姓氏”和“名字”的索引。这样的复合索引不仅可以高效地处理同时指定“姓氏”和“名字”的查询,还可以用于过滤只指定“姓氏”的查询。
遵循ESR规则
在设计复合索引时,有一个经验法则有助于确定字段的顺序:根据查询的频率和选择性,将最常用且选择性高的字段放在索引的前面。这样做可以使索引更有效地过滤数据,提高查询的性能:
在设计复合索引时,以下经验法则可以帮助您确定字段的顺序:
首先,将用于执行等值查询的字段添加到索引中。这些字段通常是经常用于查询条件的字段,例如进行精确匹配的字段。
接下来,考虑对查询结果进行排序的字段。将这些字段添加到索引中,可以使查询在排序时更加高效。
最后,将需要访问的数据范围的字段添加到索引中。这些字段可以帮助缩小索引的范围,提高查询性能。
通过遵循这个经验法则,您可以设计出更优化的复合索引,以适应不同的查询模式和需求。根据具体情况,按照等值查询字段、排序字段和数据范围字段的顺序,灵活地确定索引字段的排列,以提供更好的查询性能和响应时间。
在可能的情况下,请尽量使用覆盖查询(Covered Queries)。
覆盖查询可以直接从索引中返回结果,而无需访问源文档,因此非常高效。要确定查询是否是覆盖查询,可以使用explain()方法。如果explain()的输出显totalDocsExamined为0,说明查询是由索引覆盖的。
在尝试实现覆盖查询时,有一个常见的陷阱是_id字段默认始终返回。您需要明确地将其从查询结果中排除,或者将其添加到索引中。
在分片集群中,MongoDB内部需要访问分片键的字段。因此,只有在分片键是索引的一部分时,覆盖查询才可行。通常最好将分片键作为索引的一部分。
在考虑低基数字段上的索引时要小心
对具有少量唯一值(低基数)的字段进行查询可能会返回大的结果集。复合索引可能包含具有低基数的字段,但合并字段的值应该具有高基数。
消除不必要的索引
索引是资源密集型的:即使在MongoDB的WiredTiger存储引擎中使用压缩,它们也会消耗RAM和磁盘。此外,随着字段的更新,相关的索引也必须进行维护,这会增加额外的CPU和磁盘I/O负载。因此,我们应该谨慎评估和删除不再需要的索引。
MongoDB 还提供了工具来帮助您了解索引使用情况:
通配符索引不能替代基于工作负载的索引规划
对于具有许多临时查询模式或处理高度多态文档结构的工作负载,通配符索引提供了额外的灵活性。您可以定义一个过滤器,自动为集合中的所有匹配字段、子文档和数组创建索引。
与任何索引一样,它们也需要存储和维护,因此它们会给数据库增加开销。如果您的应用程序的查询模式事先已知,那么应该使用更有选择性的索引来处理查询访问的特定字段。
使用文本搜索来匹配字段中的单词
常规索引用于匹配字段的整个值。如果您只想在包含大量文本的字段中匹配特定单词,则应使用文本索引。
如果您在Atlas服务中运行MongoDB,请考虑使用Atlas全文搜索,它提供了一个与MongoDB数据库集成的完全托管的Lucene索引。全文搜索提供更高的性能和更大的灵活性,用于对数据库进行过滤、排序和排序,以快速呈现与用户最相关的结果。
使用部分索引
通过仅包含将通过索引访问的文档来减小索引的大小和性能开销。例如,在orderID字段上创建部分索引,只包括orderStatus为“正在进行中”的订单文档,或者仅在文档中存在emailAddress字段时创建索引。
利用多键索引查询数组
如果您的查询模式需要访问单个数组元素,请使用多键索引。MongoDB会为数组中的每个元素创建一个索引键,并且可以构建在持有标量值和嵌套文档的数组上。
避免未以左锚定或根据的正则表达式
索引按值排序。前导通配符效率低下,可能导致完整索引扫描。如果表达式中有足够的大小写敏感的前导字符,后置通配符可能是高效的。
避免大小写不敏感的正则表达式
如果使用正则表达式的唯一原因是大小写不敏感,请改用大小写不敏感索引,因为它们更快。
使用WiredTiger存储引擎中提供的索引优化
如果您自己管理MongoDB,可以将索引放在单独的卷上,从而实现更快的磁盘分页和较低的争用。有关更多信息,请参见WiredTiger选项。
使用解释计划
我们在前面的查询模式和性能分析帖子中介绍了使用MongoDB的解释计划,这是检查单个查询的索引覆盖的最佳工具。
从解释计划中工作,MongoDB提供了可视化工具,以帮助进一步改善您对索引的理解,并提供智能和自动化的建议,可添加哪些索引。
立即试用阿里云MongoDB,新用户注册即可享受三个月免费*。
扫码加入钉群,与MongoDB专家一对一沟通,了解更多阿里云MongoDB产品与方案,市场活动及线上培训等内容。