分析慢速查询我发现了一些非常奇怪的事情:对于以下操作,扫描了整个集合(33061个文档),尽管查询参数family_id:上有索引
{
"ts" : ISODate("2013-11-27T10:20:26.103Z"),
"op" : "query",
"ns" : "mydb.zones",
"query" : {
"$query" : {
"family_id" : ObjectId("52812295ea84d249934f3d12")
},
"$orderby" : {
"$natural" : 1
}
},
"ntoreturn" : 20,
"ntoskip" : 0,
"nscanned" : 33061,
"keyUpdates" : 0,
"numYield" : 91,
"lockStats" : {
"timeLockedMicros" : {
"r" : NumberLong(83271),
"w" : NumberLong(0)
},
"timeAcquiringMicros" : {
"r" : NumberLong(388988),
"w" : NumberLong(22362)
}
},
"nreturned" : 7,
"responseLength" : 2863,
"millis" : 393,
"client" : "127.0.0.1",
"user" : "mydb"
}
在谷歌上搜索了几次没有结果后,我发现去掉"$orderby": { "$natural" : 1}
,查询速度非常快,只扫描了7个文档,而不是33061个。因此,我假设在我的情况下使用$orderby
确实可以避免使用family_id上的索引。奇怪的是,在这两种情况下,结果的顺序都没有什么不同。就我对$natural order的理解而言,使用"$orderby": { "$natural" : 1}
或不使用显式顺序是同义重复的。另一个非常有趣的观察结果是,这个问题并没有出现在上限收藏上!!
这个问题产生了以下问题:
- 如果不使用任何排序/排序,那么生成的订单不应该是磁盘上的订单吗,即
$natural
订单 - 我可以创建一个用于自然排序的(复合)索引吗
- 如何在不严重性能损失的情况下反转使用索引的简单查询的排序
- 使用查询参数和orderby时,在后台会发生什么?为什么这种情况没有发生在有上限的藏品上?我想了解这种奇怪的行为
- 以上问题的答案是否独立于您是否使用分片/复制?查询在多个碎片上的自然顺序是什么
注意,我使用的是MongoDB 2.2。有一张与此问题相关的罚单:https://jira.mongodb.org/browse/SERVER-5672.尽管在那张票上,这个问题似乎也发生在有上限的收藏中,但我无法证实(可能是由于不同的mongo版本)。
就我所理解的$natural order而言,使用它是同义反复的"$orderby":{"$natural":1}或没有显式顺序。
这是对$naturalorder的错误描述。MongoDB将记录按一定的顺序存储在磁盘上,并通过一个双链表来跟踪它们$自然顺序是遍历链表时得到的顺序。但是,如果没有指定$natural,那么就是您将始终得到的——不是随机顺序,不是插入顺序,不是物理磁盘顺序,而是"逻辑"磁盘顺序——它们在遍历链表时的显示顺序。
如果不使用任何排序/排序,那么生成的订单不应该是磁盘上的订单,即$natural订单?
是的,假设您理解"磁盘顺序"并不是严格的物理顺序,而是它们在记录链接列表中的顺序。
我可以创建一个用于自然排序的(复合)索引吗?
我不知道你说的自然排序是什么意思——如果你在查询过程中使用索引,那么文档是按索引顺序遍历的,而不是按$natural顺序。
如何在不严重性能损失的情况下反转使用索引而不排序的简单查询的顺序?
您不能-如果您使用的是索引,那么您将按索引顺序获取记录-您的选择是按该顺序、与该顺序相反的顺序获取记录,或者创建一个复合索引,根据您正在搜索的字段和要排序的字段进行索引。
使用查询参数和orderby时,在后台会发生什么?为什么这种情况没有发生在有上限的藏品上?我想了解这种奇怪的行为。
会发生什么取决于可用的索引,但查询优化器会尝试使用一个既有助于筛选又有助于排序的索引——如果不可能,它会选择实际性能最好的索引。
以上问题的答案是否独立于您是否使用是否进行分片/复制?查询的自然顺序是什么多个碎片?
这是来自每个单独碎片的$natural顺序的一些非确定性合并。