MongoDB$查找未使用索引
我正在编写一个需要在两个表之间进行$lookup的查询,据我所知,foreignField必须有一个索引,以便及时执行此联接。但是,即使在字段上添加了索引,查询仍会退回到COLLSCANMongoDB$查找未使用索引,mongodb,mongodb-query,aggregation-framework,mongodb-shell,Mongodb,Mongodb Query,Aggregation Framework,Mongodb Shell,我正在编写一个需要在两个表之间进行$lookup的查询,据我所知,foreignField必须有一个索引,以便及时执行此联接。但是,即使在字段上添加了索引,查询仍会退回到COLLSCAN db.users.aggregate([ {$lookup:{ from: "transactions", localField: '_id', foreignField: 'uid', as: 'transaction' }}, { $match: { transaction: { "$size" :
db.users.aggregate([
{$lookup:{ from: "transactions", localField: '_id', foreignField: 'uid', as: 'transaction' }},
{ $match: { transaction: { "$size" : 0} } },
{ $count: "total"},
], { explain: true })
这将返回:
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "test.users",
"indexFilterSet" : false,
"parsedQuery" : {
},
"winningPlan" : {
"stage" : "COLLSCAN",
"direction" : "forward"
},
"rejectedPlans" : [ ]
}
如前所述,我在transactions集合中对uid字段进行了索引:
> db.transactions.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.transactions"
},
{
"v" : 1,
"key" : {
"uid" : 1
},
"name" : "uid_1",
"ns" : "test.transactions"
}
]
在一个包含大约700万个文档的数据库中运行查询需要几分钟的时间。我正在使用MongoDB v3.4.7。知道我做错了什么吗?提前谢谢 “阶段”:“COLLSCAN”根本不是指$lookup
聚合管道中的第一步是从“用户”集合中获取所有文档。因为根本没有提供过滤器,所以收集扫描是最有效的方法
$lookup阶段应该像任何其他查询一样进行规划,并且可能会使用索引 因为聚合管道第一阶段没有
$match
或$sort
或者,$geoNear
查询索引键,而在$match阶段,您没有查询任何索引键
案例1:如果您在第一阶段对索引键进行$match,Winning Plan
阶段将是“FETCH”
,inputStage
阶段将是“IXSCAN”
案例2:如果您在第一阶段对非索引键进行$match,Winning Plan
阶段将是“COLLSCAN”
案例3:如果在查找(根据您的查询)后对索引键进行$match,Winning Plan
阶段将是“FETCH”
,inputStage
阶段将是“IXSCAN”
案例4:如果您在查找后对非索引键执行$match(就像您执行的那样),WinningPlan
阶段将是“COLLSCAN”
对于7M记录,必须在查询中使用索引。不要做太多的索引,因为它们将存储在RAM中,并且不能正确地对索引键使用$ne
或$nin
在聚合管道中唯一可以使用索引的阶段是第一阶段,该阶段必须是
$match
或$geoNear
或$sort
。虽然$lookup
可能会在“外键”上使用索引,但目前统计数据中并未报告这一点。对于您在这里尝试的内容,不可能使用索引。请注意:在MongoDB上使用关系数据模型并试图使其更SQLish,这要么是数据建模不好的迹象,要么是技术决策不好。每次我在描述为查询的聚合中看到$lookup
,都可以通过正确的数据建模来摆脱它。感谢您提供的信息!我不知道在查找阶段需要使用索引。@NeilLunn 3.6版的规则已经更改,似乎任何阶段现在都可以使用索引。您可以添加这两个集合的示例文档吗?
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
...
}
}
"winningPlan" : {
"stage" : "COLLSCAN"
}