MongoDB在子阵列查询中发现速度慢

时间:2016-03-24 15:46:46

标签: mongodb

我有一个如下的mondoDB集合,其中包含近百万个条目:

{ 
 _id: 'object id',
 link: 'a url',
 channels: [ array of ids ]
 pubDate: Date
}

我有以下经常执行的查询:

db.articles.find({ $and: [ { pubDate: { $gte: new Date(<some date>) } }, { channels: ObjectId(<some object id>) } ] })

即使我有某些索引,查询也非常慢。最近,我对它进行了解释,结果如下:

{
    "cursor" : "BtreeCursor pubDate_-1_channels_1",
    "isMultiKey" : true,
    "n" : 2926,
    "nscannedObjects" : 4245,
    "nscanned" : 52611,
    "nscannedObjectsAllPlans" : 8125,
    "nscannedAllPlans" : 56491,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 5,
    "nChunkSkips" : 0,
    "millis" : 5378,
    "indexBounds" : {
        "pubDate" : [
            [
                ISODate("0NaN-NaN-NaNTNaN:NaN:NaNZ"),
                ISODate("2016-03-04T21:00:00Z")
            ]
        ],
        "channels" : [
            [
                ObjectId("54239b9477456cf777dd0d31"),
                ObjectId("54239b9477456cf777dd0d31")
            ]
        ]
    }
}

看起来它正在使用正确的索引,但仍然需要超过5秒才能运行。

我在这里遗漏了什么吗?我的索引有问题吗?

以下是集合btw上的索引:

[
    {
        "v" : 1,
        "name" : "_id_",
        "key" : {
            "_id" : 1
        },
        "ns" : "dbname.articles"
    },
    {
        "v" : 1,
        "name" : "pubDate_-1_channels_1",
        "key" : {
            "pubDate" : -1,
            "channels" : 1
        },
        "ns" : "dbname.articles",
        "background" : true
    },
    {
        "v" : 1,
        "name" : "pubDate_-1",
        "key" : {
            "pubDate" : -1
        },
        "ns" : "dbname.articles",
        "background" : true
    },
    {
        "v" : 1,
        "name" : "link_1",
        "key" : {
            "link" : 1
        },
        "ns" : "dbname.articles",
        "background" : true
    }
]

以下是我在集合上运行统计信息时看到的内容:

{
    "ns" : "dbname.articles",
    "count" : 2402741,
    "size" : 2838416144,
    "avgObjSize" : 1181.3242226274076,
    "storageSize" : 3311443968,
    "numExtents" : 21,
    "nindexes" : 4,
    "lastExtentSize" : 862072832,
    "paddingFactor" : 1.000000000020535,
    "systemFlags" : 0,
    "userFlags" : 0,
    "totalIndexSize" : 775150208,
    "indexSizes" : {
        "_id_" : 100834608,
        "pubDate_-1_channels_1" : 180812240,
        "pubDate_-1" : 96378688,
        "link_1" : 397124672
    },
    "ok" : 1
}

2 个答案:

答案 0 :(得分:0)

您的索引 {pubDate:-1,频道:1} 对我来说很好看。

我会尝试 {channel:1,pubDate:-1}

这个建议的原因如下:

请注意索引有订单。 您使用的索引是pubDate_-1_channels_1,它与索引channels_1_pubDate_-1不同(按相反顺序)。

根据您拥有的频道数量,我期望一个索引应该比您的查询更有效。

有关详细信息,请参阅prefixes上的手册。

答案 1 :(得分:0)

因此,根据db.my_collection.stats(),索引字段需要0.77gb("totalIndexSize" : 775150208字节),而您的集合需要3.31gb("storageSize" : 3311443968字节)。您提到您的实例使用1.5 GB的RAM。

因此,MongoDB可以将所有索引保留在内存中,但没有足够的内存来容纳所有文档。因此,当它需要对未在内存中加载的文档进行查询时,它会更慢。我敢打赌,如果你运行两次相同的查询,那么由于必要的文件已经被加载到内存中所需的时间会少得多。

我建议尝试使用5GB的RAM。执行几个查询以便将所有文档加载到内存中,然后比较速度。