Mongo根据级别范围高效查询日志集合

isunt 发布于 2019-08-14 mongodb 最后更新 2019-08-14 08:39 2 浏览

我有一个用于存储服务器日志的上限集合:

var schema = new mongoose.Schema({
    level: { type: Number, required: true },
    ...
}, { capped: 64 * 1024 * 1024, versionKey: false });
我无法确定如何通过level范围有效查询日志。以下是我想要运行的示例查询:
db.getCollection('logs').find({  
    level: { $gte: 2, $lte: 6 } 
}).sort({ _id: -1 }).limit(500)
{ _id: 1, level: 1 }进行索引没有任何意义,因为_id是唯一的,每个level将只有一个PLACEHOLDER_FOR_CODE_5,因此在最坏的情况下将检查整个集合。 如果我在{ level: 1, _id: -1 }上编制索引,最糟糕的情况是Mongo将所有日志拉到级别2,3,4,5,6,并将它们手动加入并排序,因此性能非常糟糕。有时它也决定使用{ _id: 1 }索引,这也很糟糕。 它可以一次遍历这6个索引,并在最多检查504个文档的同时获得结果。或者它只能从每个级别抽取500个结果,所以它最多可以分类2500个文档。但它不会,Mongo在涉及范围查询时显得很愚蠢。 我能想到的最快解决方案是在客户端实现最后提到的方法,因此运行5个查询,然后手动合并它们:
db.getCollection('logs').find({ level: 2 }).sort({ _id: -1 }).limit(500)
db.getCollection('logs').find({ level: 2 }).sort({ _id: -1 }).limit(500)
db.getCollection('logs').find({ level: 3 }).sort({ _id: -1 }).limit(500)
...
合并可以在客户端的O(n)中完成,只有7个日志级别,因此最多可以执行7个查询并从数据库中提取3500个文档。 有没有更好的办法?
已邀请:

tiste

赞同来自:

由于您只有7个级别,因此可以考虑使用$or查询{ level: 1, _id: -1 }索引:

db.logs.find({$or:[
    {level: 2},
    {level: 3},
    {level: 4},
    {level: 5},
    {level: 6}
]}).sort({_id:-1}).limit(500)
由于它是相等的条件,它应该使用索引,但我从来没有在上限集合上尝试过。 我会试一试并运行explain()以确认它是否有效,然后可能是enabled profiler并运行其他一些查询。