【问题标题】:First query after creating index is slow创建索引后第一次查询很慢
【发布时间】:2015-06-20 17:05:19
【问题描述】:

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

我想知道为什么会发生这种情况,是因为索引必须从磁盘转到内存吗?然后,对我来说更难理解的是我删除了索引,重新启动了 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

无索引查询,耗时3ms(explain的输出我不放,只放相关部分):

> 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,
....
}

【问题讨论】:

    标签: mongodb indexing


    【解决方案1】:

    你在 Linux 上吗? Linux 使用所有空闲内存作为磁盘缓存。即使在您重新启动 mongo 之后,缓存也会一直存在,直到系统需要它来做其他事情。即使没有索引,命中缓存的查询也会很快——因为它们命中了内存。 有一些命令可以确认 - 检查缓存命中和未命中。

    无缓冲读取(必须命中硬盘驱动器上的盘子)比内存读取花费的时间长一百倍左右(无论您读取的数据量多么小;驱动器缓存、内存缓冲区等都会提前读取兆字节,甚至如果您对单字节感兴趣)。

    请参阅https://gist.github.com/jboner/2841832 了解一些实际数字。

    我想如果你调查 http://docs.mongodb.org/manual/administration/analyzing-mongodb-performance/#administration-monitoring-page-faultshttp://docs.mongodb.org/manual/reference/glossary/#term-page-fault 您将能够确认慢速访问基本上是 100% 的页面错误(所有内容都需要从硬盘读取),而快速访问将接近 100% 的命中率(缓存读取)。

    【讨论】:

    • 不,我使用的是 Windows 8,64 位
    • 我很确定 Windows 也使用物理内存作为磁盘缓存。我认为它是任务管理器,性能选项卡中显示的“缓存”内存。所以总体思路与 Linux 相同。
    猜你喜欢
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 2019-12-12
    • 1970-01-01
    • 2021-07-23
    • 2014-09-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多