即使创建了正确的索引,Mongodb也会扫描大量文档

时间:2018-10-08 08:14:20

标签: mongodb

我遇到了mongodb查询的问题,即使在创建适当的索引以对结果文档进行排序后,扫描也仍然很高。 下面是查询

db.ratebus.find({
    $and: [{
        _id.trg: {
            $in: [54875973]
        }
    }, {
        rating: {
            $gte: 3
        }
    }]
}).sort({
    revType: -1,
    updated_at: -1
}).hint({
    _id.trg: 1,
    rating: -1,
    revType: -1,
    updated_at: -1
}).limit(10)

下面是事件探查器的输出

2018-10-08T13:03:15.986+0530 I COMMAND  [conn1370938] command jdsocial.ratebus command: find {
    find: "ratebus",
    filter: {
        $and: [{
            _id.trg: {
                $in: [54875973]
            }
        }, {
            rating: {
                $gte: 3
            }
        }]
    },
    sort: {
        revType: -1,
        updated_at: -1
    },
    hint: {
        _id.trg: 1,
        rating: -1,
        revType: -1,
        updated_at: -1
    },
    limit: 10
}
planSummary: IXSCAN {
    _id.trg: 1.0, rating: -1.0, revType: -1.0, updated_at: -1.0
}
keysExamined: 37423 docsExamined: 37423 hasSortStage: 1 cursorExhausted: 1 keyUpdates: 0 writeConflicts: 0 numYields: 292 nreturned: 10 reslen: 4047 locks: {
    Global: {
        acquireCount: {
            r: 586
        },
        acquireWaitCount: {
            r: 26
        },
        timeAcquiringMicros: {
            r: 179979
        }
    },
    Database: {
        acquireCount: {
            r: 293
        }
    },
    Collection: {
        acquireCount: {
            r: 293
        }
    }
} protocol:op_query 692ms

在此清晰可见,限制为10条记录正在扫描37423个文档。任何帮助将不胜感激。

在db中采样记录:

{
    "_id" : {
        "src" : 2584095,
        "trg" : 54877444
    },
    "revid" : "0805639673",
    "rating" : 2,
    "age" : ISODate("2012-11-14T15:41:09Z"),
    "updated_at" : ISODate("2012-11-14T15:41:09Z"),
    "hasrev" : 0,
    "revType" : 0,
    "has_rev" : false,
    "rev" : ""
},
{
    "_id" : {
        "src" : 38266391,
        "trg" : 54878562
    },
    "revid" : "0805639674",
    "rating" : 4,
    "age" : ISODate("2012-11-14T15:41:14Z"),
    "updated_at" : ISODate("2012-11-14T15:41:14Z"),
    "hasrev" : 0,
    "revType" : 0,
    "has_rev" : false,
    "rev" : "",
    "comment_id" : NumberLong("1531272078171327")
}

创建的索引:

{
    "v" : 1,
    "key" : {
        "_id.trg" : 1,
        "rating" : -1,
        "revType" : -1,
        "updated_at" : -1
    },
    "name" : "_id.trg_1_rating_-1_revType_-1_updated_at_-1",
    "ns" : "jdsocial.ratebus"
}

2 个答案:

答案 0 :(得分:3)

要完成@Alex Blex的答案,我想说排序部分应该在索引前缀中,因为您在查询中使用了$ in。

让我解释一下:MongoDB使用索引的策略如下:1)相等-2)排序-3)范围。正如您在查询的过滤器部分中使用$ in一样,此查询位于策略的“范围”部分。因此,优先级被赋予了排序阶段,它不能正确使用索引,因为它与索引前缀不匹配。

为您提供了两种解决方案:如Alex所述创建新索引,或将_id.trg: {$in: [54875973]}替换为_id.trg: {$eq: [54875973]}。唯一要选择的问题是“我是否真的需要此查询的ID范围?”

答案 1 :(得分:1)

排序部分应位于index prefix中。您拥有的索引

{
    "_id.trg" : 1,
    "rating" : -1,
    "revType" : -1,
    "updated_at" : -1
}

不支持

排序
{
    revType: -1,
    updated_at: -1
}

应该具有正确顺序的索引字段:

{
    "revType" : -1,
    "updated_at" : -1,
    "_id.trg" : 1,
    "rating" : -1
}