创建索引后的第一个查询很慢
First query after creating index is slow
我在集合中添加了一个索引。我启动的第一个查询比没有索引的同一个查询慢。下面的那些比没有索引的更快,所以这是有道理的。
我想知道为什么会发生这种情况,是因为索引必须从磁盘转到内存吗?然后,对我来说更难理解的是我删除了索引,重新启动了 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,
....
}
你在 Linux 吗? Linux 使用所有空闲内存作为磁盘缓存。即使在您重新启动 mongo 之后,缓存仍然存在,直到系统需要它来做其他事情。即使没有索引,命中缓存的查询也会很快——因为它们命中了内存。
有命令可以确认 - 检查缓存命中和未命中。
无缓冲读取(必须读取硬盘驱动器上的盘子)比内存读取时间长一百倍左右(无论您读取的数据量有多大;驱动器缓存、内存缓冲区等将提前读取兆字节,即使您对单字节感兴趣)。
有关实际数字,请参阅 https://gist.github.com/jboner/2841832。
我想如果你看看
http://docs.mongodb.org/manual/administration/analyzing-mongodb-performance/#administration-monitoring-page-faults 和
http://docs.mongodb.org/manual/reference/glossary/#term-page-fault
您将能够确认慢速访问基本上是 100% 页面错误(所有内容都需要从硬盘读取),而快速访问将接近 100% 命中率(缓存读取)。
我在集合中添加了一个索引。我启动的第一个查询比没有索引的同一个查询慢。下面的那些比没有索引的更快,所以这是有道理的。
我想知道为什么会发生这种情况,是因为索引必须从磁盘转到内存吗?然后,对我来说更难理解的是我删除了索引,重新启动了 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,
....
}
你在 Linux 吗? Linux 使用所有空闲内存作为磁盘缓存。即使在您重新启动 mongo 之后,缓存仍然存在,直到系统需要它来做其他事情。即使没有索引,命中缓存的查询也会很快——因为它们命中了内存。 有命令可以确认 - 检查缓存命中和未命中。
无缓冲读取(必须读取硬盘驱动器上的盘子)比内存读取时间长一百倍左右(无论您读取的数据量有多大;驱动器缓存、内存缓冲区等将提前读取兆字节,即使您对单字节感兴趣)。
有关实际数字,请参阅 https://gist.github.com/jboner/2841832。
我想如果你看看 http://docs.mongodb.org/manual/administration/analyzing-mongodb-performance/#administration-monitoring-page-faults 和 http://docs.mongodb.org/manual/reference/glossary/#term-page-fault 您将能够确认慢速访问基本上是 100% 页面错误(所有内容都需要从硬盘读取),而快速访问将接近 100% 命中率(缓存读取)。