我有一个包含数百万条记录的日志集合。创建新索引需要"永远"。因此,最好使用现有的索引。
现在我想知道某些错误代码的出现次数。我使用这个查询,功能上它工作正常:
db.getCollection('logs.res').aggregate([
{
$match:{
timeStamp: {
$gte: new Date('2017-05-01').getTime(), // timeStamp is Number
$lt : new Date('2017-05-02').getTime() // of ms since epoch
},
'objData.@.ErrorCode': {
$ne: null
}
}
},
{
$group: {
_id: '$objData.@.ErrorCode',
count: {$sum: 1}
}
},
{
$sort: { count: -1}
}
]);
问题是,在一天内执行此操作只需要10秒左右。我假设将使用以下索引:timeStamp_-1_objData.@.ErrorCode_1
:
{
"timeStamp" : -1,
"objData.@.ErrorCode" : 1
}
然而,MongoDB似乎坚持使用一些timeStamp: 1
索引(其他一些索引与查询无关),并扫描结果以查看某些响应是否可能附加了ErrorCode
,即使这些信息应该在索引中。
以下是explain()
:
timeStamp_-1_objData.@.ErrorCode_1
索引来加快速度?在OSX上运行MongoDB 3.2.7。
注意:我还尝试$empty: true
代替$ne: null
。它会产生相同的结果,但有些人说如果要使用复合索引,则不能使用$empty
。关于Stack Overflow的许多问题都是旧的(mongo 2.x)。
答案 0 :(得分:2)
获胜计划为CACHED PLAN
。
您可以尝试清除缓存计划。
db.getCollection('logs.res').getPlanCache().clear()
如果在清理缓存后,Mongo仍在使用错误的索引。您可以尝试设置查询计划或使用“提示”强制索引
答案 1 :(得分:1)
常规mongodb索引使用字段值和类型来构建树。
$empty: true
或$ne: null
之类的查询没有任何类型的参数,也无法从这些索引中受益。这是一种特殊情况,需要特殊的sparse index。
如果您的timeStamp_-1_objData.@.ErrorCode_1
索引创建为:
db.getCollection('logs.res').createIndex(
{
"timeStamp" : -1,
"objData.@.ErrorCode" : 1
},
{ sparse: true }
)
它应该最好地支持您的查询。否则,timeStamp_-1_objData.@.ErrorCode_1
和timeStamp_1_module_1_etc
之间没有太大区别,因为只使用了第一个字段。