创建索引后的第一个查询很慢

时间:2015-06-20 17:05:19

标签: mongodb indexing

我在集合中添加了一个索引。我启动的第一个查询比没有索引的查询慢。以下是没有索引的那些更快,所以这是有道理的。

我想知道为什么会发生这种情况,是因为索引必须从磁盘转到内存?然后,对我来说更难理解的是我删除索引,重新启动mongod,我再次创建索引并且它确实快速,而不是第一次。如果我重新启动我的计算机就像第一次一样,所以它只是第一次使用索引缓慢运行。

有人能清楚地解释这个行为吗?

下面我提供一些有关文档,索引和查询信息的信息。集合中的文档如下所示:

> db.posts.findOne()
{
        "_id" : ObjectId("557d73e1fab73211b00f3080"),
        "title" : "aaa",
        "author" : "nuevo",
        "body" : "aaa",
        "permalink" : "aaa",
        "tags" : [
                "a"
        ],
        "comments" : [ ],
        "date" : ISODate("2015-06-14T12:30:25.733Z")
}

集合的大小:

> db.posts.find().count()
1008

查询没有索引,需要3毫秒(我没有把所有输出的解释,只有相关部分):

> db.posts.explain("executionStats").find({ permalink: "ambzrbxvnorazgnqvzbw"});

{
....
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1,
                "executionTimeMillis" : 3,
                "totalKeysExamined" : 0,
                "totalDocsExamined" : 1008,
....
}

创建索引:

> db.posts.createIndex({permalink:1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 3,
        "numIndexesAfter" : 4,
        "ok" : 1
}

创建索引的查询(71毫秒):

> db.posts.explain("executionStats").find({ permalink: "ambzrbxvnorazgnqvzbw"});

{
....
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1,
                "executionTimeMillis" : 71,
                "totalKeysExamined" : 1,
                "totalDocsExamined" : 1,
....
}

使用其他永久链接重新启动相同的查询,以避免从内存(或类似的东西)中获取它。需要0毫秒:

> db.posts.explain("executionStats").find({ permalink: "orrjnueekntvjegzvbjk"});

{
....
        "executionStats" : {
                "executionSuccess" : true,
                "nReturned" : 1,
                "executionTimeMillis" : 0,
                "totalKeysExamined" : 1,
                "totalDocsExamined" : 1,
....
}

1 个答案:

答案 0 :(得分:2)

你在Linux上吗? Linux使用所有可用内存作为磁盘缓存。即使你重新启动mongo后缓存仍然存在,直到系统需要它为其他东西。即使没有任何好处,点击缓存的查询也会很快 - 因为它们会占用内存。 有命令确认 - 检查缓存命中和未命中。

无缓冲读取(一个必须击中硬盘驱动器上的板)需要比读取内存更长的时间(无论您读取的数据量是多少;驱动器缓存,内存缓冲区等都将提前读取兆字节,甚至如果你对单字节感兴趣)。

有关实际数字,请参阅ValidateOnExecution

我想如果你调查一下 https://gist.github.com/jboner/2841832http://docs.mongodb.org/manual/administration/analyzing-mongodb-performance/#administration-monitoring-page-faults 您将能够确认缓慢访问基本上是100%页面错误(所有内容都需要从硬盘读取),快速访问将接近100%命中(缓存读取)。