我正在尝试重现索引交集指令的第一个示例(http://docs.mongodb.org/manual/core/index-intersection/),但面临一个问题:mongo没有使用这两个索引
我的步骤:
添加索引:
db.orders.ensureIndex({ qty: 1 })
db.orders.ensureIndex({ item: 1 })
db.orders.getIndexes()
[{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.orders"
},
{
"v" : 1,
"key" : {
"qty" : 1
},
"name" : "qty_1",
"ns" : "test.orders"
},
{
"v" : 1,
"key" : {
"item" : 1
},
"name" : "item_1",
"ns" : "test.orders"
}]
检查查询说明:
db.orders.find( { item: "abc123", qty: { $gt: 15 } } ).explain()
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.orders",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"item" : {
"$eq" : "abc123"
}
},
{
"qty" : {
"$gt" : 15
}
}
]
},
"winningPlan" : {
"stage" : "KEEP_MUTATIONS",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"qty" : {
"$gt" : 15
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"item" : 1
},
"indexName" : "item_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"item" : [
"[\"abc123\", \"abc123\"]"
]
}
}
}
},
"rejectedPlans" : [
{
"stage" : "KEEP_MUTATIONS",
"inputStage" : {
"stage" : "FETCH",
"filter" : {
"item" : {
"$eq" : "abc123"
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"qty" : 1
},
"indexName" : "qty_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"qty" : [
"(15.0, 1.#INF]"
]
}
}
}
}
]
},
"serverInfo" : {
"host" : "localhost",
"port" : 27017,
"version" : "3.0.3",
"gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105"
},
"ok" : 1
}
正如您所见,winnerPlan仅包含item_1索引。存在包含qty_1索引的rejectedPlans。但是没有包含索引交集的计划。 我知道选择具体指数有很多条件。但在我的情况下,mongo甚至没有计划它!
有人能帮助我吗?
答案 0 :(得分:3)
SERVER-3071 JIRA issue中有关于索引选择的一些细节,但我不能说是否仍然与3.0相关。无论如何:
MongoDB 3.0.2 似乎不考虑范围查询的索引交互。但它会用于点间隔:
> db.orders.find( { item: {$eq : "abc123"}, qty: { $eq: 15 } } ).explain()
...
{
"stage" : "FETCH",
"inputStage" : {
"stage" : "KEEP_MUTATIONS",
"inputStage" : {
"stage" : "AND_SORTED",
"inputStages" : [
{
"stage" : "IXSCAN",
"keyPattern" : {
"qty" : 1
},
"indexName" : "qty_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"qty" : [
"[15.0, 15.0]"
]
}
},
{
"stage" : "IXSCAN",
"keyPattern" : {
"item" : 1
},
"indexName" : "item_1",
"isMultiKey" : false,
"direction" : "forward",
"indexBounds" : {
"item" : [
"[\"abc123\", \"abc123\"]"
]
}
}
]
}
答案 1 :(得分:1)
我们正在托管多租户网站。因此,有一个mongo集合包含有关所有客户的一些信息,例如
{customerId: 22, category: "category", region: "region", balance: 23434... }
在我们了解了Index Intersection后,我们尝试创建多个单字段索引,以支持具有可变字段的不同查询条件的查询,例如
{ customerId: 22, category: "1" }
{ customerId: 22, region: "somewhere" }
{ customerId: 22, balance: {$gt:0} }
{ customerId: 22, region: {$in: ["R1", "R2"]},balance: {$gt:0} }
....
但事实证明,从" db.collection.explain"中学习并没有发生任何交集。 由于领域有限,我们终于找到了一个解决方案来构建一个包括所有领域的复合索引。
{customerId: 1, category: 1, region: 1, balance:1...}
然后事实证明,在所有查询之下使用" large"复合指数,至于" customerId"在查询中。
{ customerId: 22, category: "1" }
{ customerId: 22, region: "somewhere" }
{ customerId: 22, balance: {$gt:0} }
{ customerId: 22, region: {$in: ["R1", "R2"]},balance: {$gt:0} }
....