Index Intersection

在本页面

2.6 版的新功能。

MongoDB 可以使用多个索引的交集来完成查询。 [1]通常,每个索引交集涉及两个索引;但是,MongoDB 可以使用多个/嵌套索引交集来解析查询。

为了说明索引交集,请考虑具有以下索引的集合orders

{ qty: 1 }
{ item: 1 }

MongoDB 可以使用两个索引的交集来支持以下查询:

db.orders.find( { item: "abc123", qty: { $gt: 15 } } )

要确定 MongoDB 是否使用索引交集,请运行explain()explain()的结果将包含AND_SORTED阶段或AND_HASH阶段。

[1]在以前的版本中,MongoDB 只能使用单个索引来满足大多数查询。带有$or子句的查询是一个 exception,该查询可以为每个$or子句使用一个索引。

索引前缀交集

使用索引交集,MongoDB 可以使用整个索引或索引前缀的交集。索引前缀是复合索引的子集,由从索引开头开始的一个或多个键组成。

考虑具有以下索引的集合orders

{ qty: 1 }
{ status: 1, ord_date: -1 }

为了完成以下在qty字段和status字段上指定条件的查询,MongoDB 可以使用两个索引的交集:

db.orders.find( { qty: { $gt: 10 } , status: "A" } )

索引交集和复合索引

索引交集并不能消除创建compound indexes的需要。但是,由于列表 Sequences(即在索引中列出键的 Sequences)和排序 Sequences(即升序或降序)都在compound indexes中起作用,因此复合索引可能不支持不包含索引前缀键或指定不同的排序 Sequences。

例如,如果集合orders具有以下复合索引,则status字段在ord_date字段之前列出:

{ status: 1, ord_date: -1 }

复合索引可以支持以下查询:

db.orders.find( { status: { $in: ["A", "P" ] } } )
db.orders.find(
   {
     ord_date: { $gt: new Date("2014-02-01") },
     status: {$in:[ "P", "A" ] }
   }
)

但不是以下两个查询:

db.orders.find( { ord_date: { $gt: new Date("2014-02-01") } } )
db.orders.find( { } ).sort( { ord_date: 1 } )

但是,如果集合具有两个单独的索引:

{ status: 1 }
{ ord_date: -1 }

这两个索引可以单独或通过索引交集来支持所有上述四个查询。

创建支持查询的复合索引还是依赖索引交集之间的选择取决于系统的具体情况。

索引交集和排序

sort()操作要求索引与查询谓词完全分开时,索引交集不适用。

例如,orders集合具有以下索引:

{ qty: 1 }
{ status: 1, ord_date: -1 }
{ status: 1 }
{ ord_date: -1 }

MongoDB 不能对以下带有排序的查询使用索引交集:

db.orders.find( { qty: { $gt: 10 } } ).sort( { status: 1 } )

也就是说,MongoDB 不会将{ qty: 1 }索引用于查询,而将单独的{ status: 1 }{ status: 1, ord_date: -1 }索引用于排序。

但是,由于索引{ status: 1, ord_date: -1 }可以满足部分查询谓词,因此 MongoDB 可以对以下查询进行排序并使用索引交集。

db.orders.find( { qty: { $gt: 10 } , status: "A" } ).sort( { ord_date: -1 } )