【问题标题】:How does MongoDB sort records when no sort order is specified?未指定排序顺序时,MongoDB 如何对记录进行排序?
【发布时间】:2022-01-24 20:04:10
【问题描述】:

当我们在没有指定任何排序顺序的情况下运行 Mongo find() 查询时,数据库内部使用什么对结果进行排序?

根据documentation on the mongo website

执行不带参数的 find() 时,数据库返回 对象按自然顺序排列。

对于标准表格,自然顺序并不是特别有用,因为, 尽管该顺序通常接近于插入顺序,但它不是 保证是。然而,对于 Capped Collections,自然顺序是 保证是插入顺序。这可能非常有用。

但是对于标准集合(无上限集合),使用什么字段对结果进行排序? 是 _id 字段还是其他字段?

编辑:

基本上,我想我想要得到的是,如果我执行以下搜索查询:

db.collection.find({"x":y}).skip(10000).limit(1000);

在两个不同的时间点:t1t2,我会得到不同的结果集吗:

  1. 在 t1 和 t2 之间没有额外的写入时?
  2. t1 和 t2 之间何时有新的写入?
  3. 在 t1 和 t2 之间添加了新的索引?

我在一个临时数据库上运行了一些测试,我得到的结果对于所有 3 个案例都是相同的() - 但我想确定并且我确定我的测试案例不是很彻底。

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    按存储顺序(文件中的顺序)返回,但不保证它们是插入顺序。它们不按 _id 字段排序。有时它看起来像是按插入顺序排序的,但它可以在另一个请求中更改。它不可靠。

    【讨论】:

      【解决方案2】:

      未指定时的默认排序顺序是什么?

      默认的内部排序顺序(或natural order)是一个未定义实现细节。维护顺序是存储引擎的额外开销,并且 MongoDB 的 API 不要求在显式 sort() 或具有关联 usage restrictions 的固定大小 capped collections 的特殊情况之外的可预测性。对于典型的工作负载,存储引擎需要尝试重用可用的预分配空间,并决定如何最有效地将数据存储在磁盘和内存中。

      在没有任何查询条件的情况下,存储引擎将以natural order 的形式返回结果(又名按照找到的顺序)。结果顺序可能与插入顺序一致,但不能保证并且不能依赖此行为(上限集合除外)。

      一些可能影响存储(自然)顺序的例子:

      • WiredTiger 在磁盘上与内存中缓存使用不同的文档表示形式,因此自然顺序可能会根据内部数据结构而改变。
      • 原始的 MMAPv1 存储引擎(在 MongoDB 4.2 中已删除)根据填充规则为文档分配记录空间。如果文档超出当前分配的记录空间,则文档位置(和自然顺序)将受到影响。由于已删除或移动文档,新文档也可以插入标记为可重复使用的存储中。
      • 复制使用idempotent oplog 格式在副本集成员之间一致地应用写入操作。每个副本集成员都维护本地数据文件,这些数据文件可以按自然顺序变化,但在应用 oplog 更新时将具有相同的数据结果。

      如果使用索引会怎样?

      如果使用索引,文档将按照它们被发现的顺序返回(它必须匹配插入顺序或 I/O 顺序)。如果使用了多个索引,则顺序在内部取决于在重复数据删除过程中首先标识文档的索引。

      如果您想要一个可预测的排序顺序,您必须在查询中包含明确的 sort(),并为您的排序键提供唯一值。

      上限集合如何维护插入顺序?

      在上限集合中为自然顺序记录的实现例外是由它们的特殊使用限制强制执行的:文档按插入顺序存储,但现有文档大小不能增加,并且不能显式删除文档。排序是封顶集合设计的一部分,可确保最旧的文档首先“过期”。

      【讨论】:

      • 这是否意味着如果我在两个不同的点运行相同的查找命令: db.collection.find({"x":y}).skip(20000).limit(1000)时间,我会得到不同的结果集?如果两个命令之间没有写入会发生什么?
      • @saurabhj:添加了一些会影响自然顺序的示例。如果文档已被移动/删除,您可能会得到不同的结果集。如果没有文档插入/更新/删除,您应该得到相同的结果。添加索引不会影响文档在磁盘上的位置。
      • 还应该补充一点,如果您使用replication,则副本集成员之间的自然顺序可能会有所不同。
      • 有谁知道如何强制此处评论的 2 点中的任何一个?我们尝试修改文档,但它们仍以插入顺序返回...我很好奇自然顺序是否可以与插入顺序不同。
      • 强制执行默认顺序(例如{createdAt: -1})对于实现Optimistic UI 模式(在创建/更新/删除后无需等待服务器响应而更新缓存中的数据列表)是必要的。否则无法匹配客户端乐观顺序和服务器响应顺序。
      猜你喜欢
      • 2015-07-20
      • 2013-03-29
      • 1970-01-01
      • 2012-12-08
      相关资源
      最近更新 更多