【无耻的打个小广告】: 接下来我会陆续发出一些翻译文档,第一时间会发在我的微信公众号上,欢迎大家订阅我(公众号:mongodb_side)
索引交集
github版本 - 119de9c84cb178c60c13b69774831d507be7e63a
翻译、编辑陈杰(6623662005@163.com)
2.6新增。
MongoDB可以使用多个索引的交集来实现查询。[1] 一般来说,每个索引交集涉及2个索引;但是MongoDB可以使用多个/嵌套索引交集来处理一个查询。
举例说明一下索引交集,有个orders集合包含下面2个索引:
{ qty:1 }
{ item:1 }
MongoDB能使用这两个索引的交集来支持下边的查询:
db.orders.find( { item:"abc123", qty: { $gt:15 } } )
对于使用了索引交集的查询计划,explain()显示的结果会在cursor 字段中返回Complex Plan值。
之前的版本只能用单索引来实现大多数查询。只有一种情况是例外的,当查询中有 $or操作符时,每个$or条件都可以单独使用一个索引。
索引前辍交集
MongoDB可以使用整个索引来做交集,也可以使用索引辍来做交集。索引前辍是复合索引的子集,从第一个索引开始的一个或多个索引。
假设集合 orders 有如下索引:
{ qty:1 }
{ status:1, ord_date:-1 }
下面这个查询指定了两个条件qty 和status,MongoDB可以用上面两个索引的交集来实现查询:
db.orders.find( { qty: { $gt:10 } , status:"A" } )
索引交集和复合索引
索引交集并没有消减对复合索引的需求。但是因为复合索引的定义顺序(即复合索引定义的先后顺序)和排序方向(即升序或降序)对于复合索引来说是有关系的,复合索引可能不能支持那种查询条件不包含索引前辍或者不按指定排序方向的查询。
例如,集合orders有下面这个复合索引,status字段在ord_date字段前面:
{ status:1, ord_date:-1 }
这个复合索引可以支持下面的查询:
db.orders.find( { status: { $in: ["A", "P" ] } } )
db.orders.find(
{
ord_date: { $gt:newDate("2014-02-01") },
status: {$in:[ "P", "A" ] }
}
)
但是下面两个查询不支持:
db.orders.find( { ord_date: { $gt:newDate("2014-02-01") } } )
db.orders.find( { } ).sort( { ord_date:1 } )
但是,如果集合有两个单独的索引:
{ status: 1 }
{ ord_date: -1 }
这两个索引可以通过单独或索引交集的方式支持以上4个查询。
其实就是在通过具体的系统需求情况在创建复合索引和索引交集中做权衡选择。
另见
索引交集和排序
当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 }覆盖了部分的查询条件
db.orders.find( { qty: { $gt:10 } , status:"A" } ).sort( { ord_date:-1 } )