$ natural order避免索引。 orderby如何影响索引的使用?

时间:2013-12-10 09:27:03

标签: mongodb sorting indexing query-performance

分析慢查询我发现了一些非常奇怪的事情:对于以下操作,即使查询参数family_id上有索引,也会扫描整个集合(33061文档):

{
    "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"
}

在没有结果的Google搜索之后,我发现忽略"$orderby": { "$natural" : 1}查询非常快,只扫描了7个文档而不是33061.所以我假设在我的情况下使用$orderby会避免在family_id上使用索引。奇怪的是,在任何一种情况下,结果顺序都没有区别。据我了解$自然顺序,使用"$orderby": { "$natural" : 1}或没有明确的顺序是同义的。另一个非常有趣的观察是,这个问题不会出现在上限集合上!!

此问题产生了以下问题:

  1. 如果没有使用任何排序/排序,结果订单不应该是磁盘上的订单,即$natural订单?
  2. 我可以创建一个自然排序的(化合物)索引吗?
  3. 如何在没有严重性能损失的情况下反转使用索引而不进行排序的简单查询的顺序?
  4. 使用查询参数和orderby时幕后会发生什么?为什么这不会发生在上限集合中?我想了解这种奇怪的行为。
  5. 上述问题的答案是否与您是否使用分片/复制无关?查询多个分片的自然顺序是什么?
  6. 注意我使用的是MongoDB 2.2。有一个与此问题相关的故障单:https://jira.mongodb.org/browse/SERVER-5672。虽然在票证中似乎也出现了问题,但我无法确认(可能是因为mongo版本不同)。

1 个答案:

答案 0 :(得分:1)

  

据我了解$自然顺序,它是重复使用的   “$ orderby”:{“$ natural”:1}或没有明确的订单。

这是$自然顺序的错误描述。 MongoDB以磁盘上的某种顺序存储记录,并通过双向链表跟踪它们。 $ natural order是您遍历链表时获得的顺序。但是,如果您执行 not 指定$ natural,那么 将始终获得 - 不是随机顺序,不是插入顺序,不是物理磁盘顺序,而是“逻辑”磁盘order - 遍历链表时它们出现的顺序。

  

如果不使用任何排序/排序,则不应该生成订单   磁盘上的订单,即$ natural order?

是的,假设你明白“磁盘订单”不是严格的物理订单,它的顺序是它们在链接的记录列表中。

  

我可以创建一个自然排序的(化合物)索引吗?

我不清楚你的意思是自然排序 - 如果你在查询期间使用索引,那么文档将按索引顺序遍历,而不是以$自然顺序遍历。

  

如何在不产生严重性能损失的情况下,反转使用索引而不进行排序的简单查询的顺序?

您不能 - 如果您正在使用索引,那么您将按索引顺序获取记录 - 您的选项是按顺序获取它们,与该顺序相反或创建复合索引,您可以按字段索引搜索您想要排序的字段。

  

使用查询参数和orderby后幕后会发生什么?为什么这不会发生在上限集合中?我想了解这种奇怪的行为。

发生什么取决于可用的索引,但查询优化器尝试使用有助于过滤和排序的索引 - 如果不可能,它将选择具有最佳实际性能的索引。

  

上述问题的答案是否与您是否使用无关   是否分片/复制?查询的自然顺序是什么?   多个分片?

这是来自每个单独碎片的$ natural命令的一些非确定性合并。