Mongodb查询过慢

时间:2014-06-16 15:51:36

标签: mongodb

我有一组推文,其中包含userid和tweeted_at(date)的索引。我想在用户的集合中找到最旧和最新推文的日期,但查询运行速度非常慢。

我用过解释,这就是我得到的。我试着阅读文档进行解释,但我不明白这里发生了什么。解释只是排序吗?如果是这样,为什么在使用索引时需要这么长时间?

    > db.tweets.find({userid:50263}).sort({tweeted_at:-1}).limit(1).explain(1)
{
        "cursor" : "BtreeCursor tweeted_at_1 reverse",
        "isMultiKey" : false,
        "n" : 0,
        "nscannedObjects" : 12705,
        "nscanned" : 12705,
        "nscannedObjectsAllPlans" : 12705,
        "nscannedAllPlans" : 12705,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 188,
        "nChunkSkips" : 0,
        "millis" : 7720,
        "indexBounds" : {
                "tweeted_at" : [
                        [
                                {
                                        "$maxElement" : 1
                                },
                                {
                                        "$minElement" : 1
                                }
                        ]
                ]
        },
        "allPlans" : [
                {
                        "cursor" : "BtreeCursor tweeted_at_1 reverse",
                        "isMultiKey" : false,
                        "n" : 0,
                        "nscannedObjects" : 12705,
                        "nscanned" : 12705,
                        "scanAndOrder" : false,
                        "indexOnly" : false,
                        "nChunkSkips" : 0,
                        "indexBounds" : {
                                "tweeted_at" : [
                                        [
                                                {
                                                        "$maxElement" : 1
                                                },
                                                {
                                                        "$minElement" : 1
                                                }
                                        ]
                                ]
                        }
                }
        ],
        "server" : "adams-server:27017",
        "filterSet" : false,
        "stats" : {
                "type" : "LIMIT",
                "works" : 12807,
                "yields" : 188,
                "unyields" : 188,
                "invalidates" : 0,
                "advanced" : 0,
                "needTime" : 12705,
                "needFetch" : 101,
                "isEOF" : 1,
                "children" : [
                        {
                                "type" : "FETCH",
                                "works" : 12807,
                                "yields" : 188,
                                "unyields" : 188,
                                "invalidates" : 0,
                                "advanced" : 0,
                                "needTime" : 12705,
                                "needFetch" : 101,
                                "isEOF" : 1,
                                "alreadyHasObj" : 0,
                                "forcedFetches" : 0,
                                "matchTested" : 0,
                                "children" : [
                                        {
                                                "type" : "IXSCAN",
                                                "works" : 12705,
                                                "yields" : 188,
                                                "unyields" : 188,
                                                "invalidates" : 0,
                                                "advanced" : 12705,
                                                "needTime" : 0,
                                                "needFetch" : 0,
                                                "isEOF" : 1,
                                                "keyPattern" : "{ tweeted_at: 1.
0 }",
                                                "boundsVerbose" : "field #0['twe
eted_at']: [MaxKey, MinKey]",
                                                "isMultiKey" : 0,
                                                "yieldMovedCursor" : 0,
                                                "dupsTested" : 0,
                                                "dupsDropped" : 0,
                                                "seenInvalidated" : 0,
                                                "matchTested" : 0,
                                                "keysExamined" : 12705,
                                                "children" : [ ]
                                        }
                                ]
                        }
                ]
        }
}
>

> db.tweets.getIndexes()
[
        {
                "v" : 1,
                "key" : {
                        "_id" : 1
                },
                "name" : "_id_",
                "ns" : "honeypot.tweets"
        },
        {
                "v" : 1,
                "unique" : true,
                "key" : {
                        "tweet_id" : 1
                },
                "name" : "tweet_id_1",
                "ns" : "honeypot.tweets",
                "dropDups" : true
        },
        {
                "v" : 1,
                "key" : {
                        "tweeted_at" : 1
                },
                "name" : "tweeted_at_1",
                "ns" : "honeypot.tweets"
        },
        {
                "v" : 1,
                "key" : {
                        "keywords" : 1
                },
                "name" : "keywords_1",
                "ns" : "honeypot.tweets"
        },
        {
                "v" : 1,
                "key" : {
                        "user_id" : 1
                },
                "name" : "user_id_1",
                "ns" : "honeypot.tweets"
        }
]
>

2 个答案:

答案 0 :(得分:4)

通过查看光标字段,您可以看到使用了哪个索引:

"cursor" : "BtreeCursor tweeted_at_1 reverse",

BtreeCursor表示查询使用了索引,tweeted_at_1 reverse是使用的索引的名称。

您应该查看解释中每个字段的documentation,以查看每个字段的详细说明。

您的查询持续了7720毫秒(milis),扫描了12705个文档(nscanned)。

查询速度很慢,因为MongoDB扫描了符合条件的所有文档。发生这种情况是因为MongoDB没有使用您的索引进行查询,而是用于对数据进行排序。

要创建将用于查询和排序的索引,您应该创建compound index。复合索引是引用多个字段的单个索引结构。您可以创建最多31个字段的复合索引。您可以创建这样的复合索引(顺序或字段很重要):

db.tweets.ensureIndex({userid: 1, tweeted_at: -1});

此索引将用于搜索userid字段并按tweeted_at字段排序。

您可以阅读并查看有关添加用于排序here的索引的更多示例。

修改 如果您有其他索引,MongoDB可能正在使用它们。在测试查询性能时,可以使用hint来使用特定索引。

在测试查询的性能时,您应该始终进行多项测试并采取约。结果。

此外,如果查询速度很慢,即使使用索引,我也会检查服务器上是否有足够的内存。从磁盘加载数据比从内存加载慢几个数量级。您应该始终确保有足够的RAM,以便所有数据和索引都适合内存。

答案 1 :(得分:0)

看起来你需要在tweeted_at和userid上创建一个索引。

 db.tweets.ensureIndex({'tweeted_at':1, 'userid':1})

这应该使查询确实非常快(但是以存储和插入时间为代价)