MongoDB没有使用我的索引

时间:2017-09-20 15:54:36

标签: mongodb indexing compound-index

我有一个包含数百万条记录的日志集合。创建新索引需要"永远"。因此,最好使用现有的索引。

现在我想知道某些错误代码的出现次数。我使用这个查询,功能上它工作正常:

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()

enter image description here

  • 有没有办法使用 timeStamp_-1_objData.@.ErrorCode_1 索引来加快速度?
  • 为什么不使用此索引?我可能误解了此查询中索引的使用方式。

在OSX上运行MongoDB 3.2.7。

注意:我还尝试$empty: true代替$ne: null。它会产生相同的结果,但有些人说如果要使用复合索引,则不能使用$empty。关于Stack Overflow的许多问题都是旧的(mongo 2.x)。

2 个答案:

答案 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_1timeStamp_1_module_1_etc之间没有太大区别,因为只使用了第一个字段。