索引并集
重要
MongoDB 可以使用多个索引的交集来完成查询。 一般来说,每个索引交集涉及两个索引;但是,MongoDB 可以使用多个/嵌套索引交集来解析查询。
为了说明索引交集,请考虑具有以下索引的 orders
collection:
{ qty: 1 } { item: 1 }
MongoDB 可以使用两个索引的交集来支持以下查询:
db.orders.find( { item: "abc123", qty: { $gt: 15 } } )
要确定 MongoDB 是否使用了索引交集,请运行explain()
; explain()的结果将包括AND_SORTED
阶段或AND_HASH
阶段。
索引前缀交集
对于索引交集,MongoDB 可以使用整个索引或索引前缀的交集。 索引前缀是复合索引的子集,由从索引开头开始的一个或多个键组成。
考虑具有以下索引的collectionorders
:
{ qty: 1 } { status: 1, ord_date: -1 }
要完成以下在qty
字段和status
字段上同时指定条件的查询,MongoDB 可以使用两个索引的交集:
db.orders.find( { qty: { $gt: 10 } , status: "A" } )
索引交集和复合索引
索引交集并不能消除创建复合索引的需要。 但是,因为列表顺序(即键在索引中列出的顺序)和排序顺序(即 升序或降序),但在复合索引中,复合索引可能不支持不包含索引前缀键或指定不同排序顺序的查询条件。
注意
对于 MongoDB Atlas 上托管的部署,请考虑使用 Atlas Search 索引,以避免由于字段顺序造成的限制。
例如,如果collection 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 } )
但是,如果collection有两个单独的索引:
{ status: 1 } { ord_date: -1 }
这两个索引可以单独或通过索引交集支持上述所有四个查询。
选择创建支持查询的复合索引还是依赖索引交集取决于系统的具体情况。
索引交集和排序
当sort()
操作需要将索引与查询谓词完全分开时,索引交集不适用。
例如, orders
collection 具有以下索引:
{ 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
}
索引进行排序。
但是,MongoDB 可以对以下带排序的查询使用索引交集,因为索引{ status: 1, ord_date: -1 }
可以满足部分查询谓词的条件。
db.orders.find( { qty: { $gt: 10 } , status: "A" } ).sort( { ord_date: -1 } )
索引交集和 Atlas Search 索引
如果您使用MongoDB Atlas ,则当查询优化器选择涉及索引交集的计划时,您可以创建Atlas Search索引来完成查询。 与复合索引不同, Atlas Search索引中的字段可以按任意顺序定义。 因此, Atlas Seach索引可以支持以下查询:
指定与索引排序顺序不同的排序顺序。
包含不属于索引前缀的字段。
有关在需要索引交集时使用Atlas Search索引的教程,请参阅使用Atlas Search进行灵活查询。
注意
Atlas Search 索引仅适用于 MongoDB Atlas 集群,不适用于自托管部署。要了解详情,请参阅: