MongoDB 2d复合索引扫描的文档多于返回的文档

时间:2018-07-06 17:50:13

标签: mongodb indexing mongodb-query query-optimization

我的数据格式如下:

{_id: ObjectId('...'), pos: [100, 100], uid: null}
{_id: ObjectId('...'), pos: [150, -100], uid: null}
{_id: ObjectId('...'), pos: [500, 137], uid: ObjectId('5b38d9876c08726511739141')}
{_id: ObjectId('...'), pos: [-980, 540], uid: uid: ObjectId('5b38d9876c08726511739141')}
...

我创建了以下索引:

{
    "v" : 2,
    "key" : {
        "pos" : "2d",
        "uid" : 1
    },
    "name" : "pos_2d_uid_1",
    "ns" : "coll.entities",
    "min" : -104857600,
    "max" : 104857600
}

然后我通过explain运行以下查询:

db.coll.find({pos: {$geoWithin: {$box: [[-6949, 4064], [6408, -6468]]}}, uid: null});

并获得以下结果:

nReturned: 30
totalKeysExamined: 87753
totalDocsExamined: 87743

该馆藏中有大约50万个文档,因此它没有扫描整个馆藏(并且它使用的是“ FETCH”阶段和正确的索引)。这些查询由于扫描了很多文档而非常慢,但是由于索引正确匹配,为什么要扫描那么多文档而不是仅扫描匹配的数字?

1 个答案:

答案 0 :(得分:0)

我最终要做的是完全废弃地理空间查询,然后将其替换为两个范围查询,如下所示:

db.coll.find({uid: null, 'pos.0': {$gte: -6949, $lte: 6408}, 'pos.1': {$gte: -6468, $lte: 4064}});

然后我创建了以下索引:

{uid: 1, 'pos.0': 1, 'pos.1': 1}

此更改导致totalDocsExamined匹配nReturned,从而大大降低了MongoDB服务器的负载。