【问题标题】:$natural order avoids indexes. How does orderby effect the use of indexes?$natural order 避免索引。 orderby 如何影响索引的使用?
【发布时间】:2013-12-27 17:43:33
【问题描述】:

分析慢查询我发现了一些非常奇怪的事情:对于以下操作,即使查询参数 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"
}

在一些没有结果的谷歌搜索之后,我发现省略了 "$orderby": { "$natural" : 1} 查询非常快,只扫描了 7 个文档而不是 33061。所以我假设在我的情况下使用 $orderby 确实避免使用索引家庭编号。奇怪的是,结果的顺序在任何一种情况下都没有不同。据我了解 $natural 顺序重复使用 "$orderby": { "$natural" : 1} 或没有明确的顺序。另一个非常有趣的观察是,这个问题不会出现在 capped collection 上!!

这个问题产生以下问题:

  1. 如果不使用任何排序/排序,生成的订单不应该是磁盘上的订单,即$natural order?
  2. 我能否创建一个(复合)索引以用于自然排序?
  3. 如何在不严重损失性能的情况下反转使用索引的简单查询的顺序而不进行排序?
  4. 在使用查询参数和 orderby 时,幕后会发生什么?为什么这不会发生在有上限的集合上?我想了解这种奇怪的行为。
  5. 上述问题的答案是否与您是否使用分片/复制无关?对多个分片进行查询的自然顺序是什么?

注意我使用的是 MongoDB 2.2。有一张与此问题相关的票:https://jira.mongodb.org/browse/SERVER-5672。虽然在那张票中似乎问题也出现在有上限的集合中,但我无法确认(可能是由于不同的 mongo 版本)。

【问题讨论】:

    标签: mongodb sorting indexing query-performance


    【解决方案1】:

    据我了解 $natural order 是重言式使用 "$orderby": { "$natural" : 1} 或没有明确的顺序。

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

    如果不使用任何排序/排序,生成的顺序不应该是 磁盘上的顺序,即$自然顺序?

    是的,假设您了解“磁盘顺序”不是严格的物理顺序,而是它们在记录链接列表中的顺序。

    我可以创建一个(复合)索引以用于自然排序吗?

    我不知道您所说的自然排序是什么意思 - 如果您在查询期间使用索引,文档将按索引顺序而不是 $natural 顺序遍历。

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

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

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

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

    以上问题的答案是否独立于你是否使用 分片/复制与否?查询的自然顺序是什么 多个分片?

    这是来自每个分片的 $natural 订单的一些非确定性合并。

    【讨论】:

    • 嗯,也许文档应该更多地说明您刚才提到的内容,而且我记得当我问您是否可以始终依赖订单时,eliot 告诉我 mongodb 以查找顺序返回 :/是静态的
    • 如果您的数据库是静态的(也就是完全不变),那么您只能依靠它是静态的,而且这不会是一个数据库,对吗?您应该依赖查找顺序(也称为 $natural 顺序)来预测,因为随着您执行更多的写入操作,$natural 顺序可以并且将会改变。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-20
    相关资源
    最近更新 更多