为什么MongoDB不使用索引交集?
我试图重现索引交叉指令的第一个示例,但面临一个问题:mongo不同时使用两个索引 我的步骤: 下载mongo 3.0.3并安装它 运行mongod:mongod.exe-dbpath d:\data文件夹为空 运行mongo:mongo.exe 添加索引:为什么MongoDB不使用索引交集?,mongodb,indexing,database-indexes,mongodb-indexes,Mongodb,Indexing,Database Indexes,Mongodb Indexes,我试图重现索引交叉指令的第一个示例,但面临一个问题:mongo不同时使用两个索引 我的步骤: 下载mongo 3.0.3并安装它 运行mongod:mongod.exe-dbpath d:\data文件夹为空 运行mongo:mongo.exe 添加索引: db.orders.ensureIndex({ qty: 1 }) db.orders.ensureIndex({ item: 1 }) db.orders.getIndexes() [{ "v" : 1, "
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
}
正如您所看到的,winningPlan只包含项_1索引。存在包含数量1索引的拒绝计划。但没有包含索引交叉点的计划。
我知道选择具体指标有很多条件。但就我而言,mongo甚至没有计划
有人能帮我吗?中有一些关于索引选择的详细信息,但我不能说这些是否仍然与3.0相关。无论如何:
MangGDB 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\"]"
]
}
}
]
}
我们正在托管一个多租户网站。所以有一个mongo集合,它保存了一些关于所有客户的信息,例如
{customerId: 22, category: "category", region: "region", balance: 23434... }
在了解了索引交集之后,我们尝试创建多个单字段索引,以支持具有可变字段的不同查询条件的查询,例如
{ 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...}
然后发现,就查询中的customerId而言,下面所有查询都使用大型复合索引
{ customerId: 22, category: "1" }
{ customerId: 22, region: "somewhere" }
{ customerId: 22, balance: {$gt:0} }
{ customerId: 22, region: {$in: ["R1", "R2"]},balance: {$gt:0} }
....
FWIW与MongoDB 3.0.2的工作原理相同。数据库中有多少文档?解释说什么?查询需要多长时间?如果有的话,数据字段的分布是什么?那么,在现实生活中,基本上索引相交似乎从未发生过?根据我的测试,对$in查询中超过1项也不起作用:观察与v3.4.10相同的行为进一步观察:提示对复合索引前缀不起作用仅对整个复合索引起作用;索引交集似乎不适用于复合索引前缀,仅适用于单个索引。不过,仅仅添加这么大的复合索引并没有多大帮助。在您提供的四个查询示例中,后三个仅使用复合索引的customerId前缀,而第一个使用复合索引的customerId加上类别前缀。如果您试图为这四个查询建立索引,那么只在前两个字段上建立复合索引会更好。只是说,没有人会想到,一个庞大的复合索引会加速对其中任何字段的任意查询过滤: