我正在使用以下查询(使用NodeJS适配器)来查找集合中缺少的索引。
findIndexGaps(collection, index, from, to, callback) {
var aggregateOptions = [
{ $group: {_id: null, min: {$min: from}, max: {$max: to} } },
{ $addFields: {rangeIds: {$range: ['$min', '$max'] } } },
{ $lookup: {from: collection, localField: 'rangeIds', foreignField: index, as: 'entries'} },
{ $project: {_id: 0, missingIds: { $setDifference: ['$rangeIds', '$entries.'+index]}}}
];
this.connection.collection(collection).aggregate(aggregateOptions, {allowDiskUse: true}).toArray(...);
}
我已为集合设置了唯一索引item_id
。当我使用参数from = 0
,to = 50
和index =' item_id'时,查询会返回正确的结果。但是,执行需要将近9秒,这对于将返回最多50个结果的查询来说是不可接受的。
我查询的集合非常庞大。在撰写本文时,它包含大约4200万条目,每月增长约1000万。我可以使用小的查询范围(如上例中使用的50),但我希望这些查询尽可能高效。
导致这种放缓的原因是什么,我该如何优化呢?
答案 0 :(得分:1)
我发现减速的原因是因为我在分组之前没有包含$match
运算符,所以它会加载我的整个数据集,然后分组,然后搜索间隙。
这是我用来解决问题的选项:
//In aggregateOptions[]:
{ $match: { [index]: { $lte: to, $gte: from } } }
答案 1 :(得分:1)
然而,执行需要将近9秒,这对于将返回最多50个结果的查询来说是不可接受的。
查询的性能不取决于返回的结果数量;它取决于生成结果所执行的工作量以及执行工作时可用的资源量。
完全诊断性能需要更多信息,但我怀疑操作很慢,因为$ group阶段正在扫描集合中的所有4200万个文档并汇总结果。考虑添加初步$match阶段以过滤掉不需要汇总的数据。
您还应该确保$ lookup阶段查询在两个集合上都被编入索引(例如索引' rangeIds'在源集合上以及索引字段在外部集合上的任何内容)。
答案 2 :(得分:0)
请咨询您的平台支持团队或文档 - 集合可以处理的最佳条目数。这对我来说听起来像一个大数据案例。我认为MongoDB可能不支持超过十万个条目的东西 - 我猜测大量的数据你可能需要更快的高级数据库产品。