Docs 菜单

Docs 主页开发应用程序MongoDB Manual

复合索引

在此页面上

  • 兼容性
  • 创建复合索引
  • 排序顺序
  • 前缀
  • 索引并集
  • 稀疏复合索引
  • 其他注意事项

MongoDB 支持复合索引,其中单个索引结构保存对集合文档中多个字段[1]的引用。 下图说明了两个字段上的复合索引的示例:

``userid`` 字段(升序)和 ``score`` 字段(降序)的复合索引图。索引首先按 ``userid`` 字段排序,然后按 ``score`` 字段排序。
[1] MongoDB 将任何复合索引的字段限制为 32 个。

复合索引可以支持匹配多个字段的查询。

您可以对 MongoDB Atlas 中托管的部署使用复合索引。

要了解有关为 MongoDB Atlas 中托管的部署管理索引的更多信息,请参阅创建、查看、删除和隐藏索引

要创建复合索引,请使用类似于以下原型的操作:

db.collection.createIndex( { <field1>: <type>, <field2>: <type2>, ... } )

索引规范中的字段值描述了该字段的索引类型。 例如,值为 1指定按升序对项目进行排序的索引。 值为-1指定按降序对项目进行排序的索引。 有关其他索引类型,请参阅索引类型。

索引字段的顺序对给定查询的特定索引的有效性有很大影响。For most compound indexes, following the ESR (Equality, Sort, Range) rule helps to create efficient indexes.

重要

从 MongoDB 4.4 开始:

在 MongoDB 4.2 或更早版本中:

考虑一个名为products的集合,其中包含类似于以下文档的文档:

{
"_id": ObjectId(...),
"item": "Banana",
"category": ["food", "produce", "grocery"],
"location": "4th Street Store",
"stock": 4,
"type": "cases"
}

以下操作在itemstock字段上创建升序索引:

db.products.createIndex( { "item": 1, "stock": 1 } )

复合索引中列出的字段顺序很重要。该索引将包含对文档的引用,这些文档首先按item字段的值排序,然后在item字段的每个值中按 stock 字段的值排序。有关详细信息,请参阅排序顺序

复合索引除了支持匹配所有索引字段的查询外,还支持匹配索引字段前缀的查询。 也就是说,索引支持对item字段以及itemstock字段的查询:

db.products.find( { item: "Banana" } )
db.products.find( { item: "Banana", stock: { $gt: 5 } } )

有关详细信息,请参阅前缀。

索引按升序 ( 1 ) 或降序 ( -1 ) 存储对字段的引用。对于单字段索引,键的排序顺序并不重要,因为 MongoDB 可以沿任一方向遍历索引。但是,对于复合索引,排序顺序对于确定索引是否可以支持排序操作很重要。

考虑一个collectionevents,其中包含具有字段usernamedate的文档。应用程序可以发出查询,返回的结果首先按升序username值排序,然后按降序(即从最近到最后) date值排序,例如:

db.events.find().sort( { username: 1, date: -1 } )

或查询返回的结果首先按降序username值排序,然后按升序date值排序,例如:

db.events.find().sort( { username: -1, date: 1 } )

以下索引可以支持这两种排序操作:

db.events.createIndex( { "username" : 1, "date" : -1 } )

但是,上述索引支持先按username值升序排序,然后再按date值升序排序,如下所示:

db.events.find().sort( { username: 1, date: 1 } )

有关排序顺序和复合索引的更多信息,请参阅使用索引对查询结果进行排序。

索引前缀是索引字段的起始子集。例如,考虑以下复合索引:

{ "item": 1, "location": 1, "stock": 1 }

该索引具有以下索引前缀:

  • { item: 1 }

  • { item: 1, location: 1 }

对于复合索引,MongoDB 可以使用索引来支持对索引前缀的查询。 因此,MongoDB 可以使用该索引对以下字段进行查询:

  • item 字段。

  • item字段location字段,

  • item字段 location字段stock字段。

MongoDB 还可以使用索引支持对itemstock字段的查询,因为item字段对应于前缀。 但是,在这种情况下,索引在支持查询方面的效率不如索引仅位于itemstock上。

item由于对stock 和 的查询省略了location 索引前缀,因此无法使用stock 之后的location 索引字段。只有索引中的item字段可以支持此查询。 有关更多信息,请参阅创建索引以支持查询。 索引:

  1. 匹配item的键。

  2. IXSCAN阶段对stock字段执行筛选。

  3. 返回筛选后的结果。

例如,考虑对"item": "saccharomyces cerevisiae""stock": 60的查询。 如果collection包含 10000 个与"item": "saccharomyces cerevisiae"匹配的文档,而其中只有 100 个与"stock": 60匹配的文档,则该查询将检查 10000 个键。在IXSCAN阶段,查询按stock字段筛选这些键,并且仅向下一阶段返回 100 个结果。

MongoDB 无法使用该索引来支持包含以下字段的查询,因为如果没有item字段,所列字段均不对应于前缀索引:

  • location 字段。

  • stock 字段,或

  • locationstock 字段。

如果您的集合同时具有复合索引和前缀索引(例如 { a: 1, b: 1 }{ a: 1 } ),如果两个索引都没有稀疏或唯一约束,那么您可以删除前缀上的索引(例如 { a: 1 } )。 MongoDB 将在所有需要使用前缀索引的情况下使用复合索引。

从 2.6 版本开始,MongoDB 可以使用索引交集来完成查询。 选择创建支持查询的复合索引还是依赖索引交集取决于系统的具体情况。 有关更多详细信息,请参阅索引交集和复合索引

复合索引可以包含不同类型的稀疏索引。索引类型的组合决定了复合索引与文档的匹配方式。

本表汇总了包含不同类型稀疏索引的复合索引的行为:

复合索引组件
复合索引行为
升序索引
降序索引
仅对至少包含一个键值的文档进行索引。
升序索引
降序索引
仅当文档包含一个 geospatial 字段的值时,才为文档编制索引。不在升序或降序索引中索引文档。
升序索引
降序索引
仅当文档与一个 text 字段匹配时,才为文档编制索引。不在升序或降序索引中索引文档。

在索引构建期间,应用程序可能会遇到性能下降或要索引集合的读/写权限受限的问题。

有关索引构建过程的更多信息,请参阅填充collection上索引构建,特别是复制环境中的索引构建部分。

某些驱动程序使用NumberLong(1)而不是1来指定索引顺序。 生成的索引是相同的。

← 单字段索引