131

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

根据mongo 网站上的文档

当执行不带参数的 find() 时,数据库会以正向自然顺序返回对象。

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

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

编辑:

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

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

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

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

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

4

2 回答 2

145

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

默认的内部排序顺序(或自然顺序)是未定义的实现细节。维护顺序是存储引擎的额外开销,并且 MongoDB 的 API 不要求在明确或具有相关使用限制sort()的固定大小上限集合的特殊情况之外的可预测性。对于典型的工作负载,存储引擎需要尝试重用可用的预分配空间,并决定如何最有效地将数据存储在磁盘和内存中。

如果没有任何查询条件,存储引擎将按自然顺序(也就是找到它们的顺序)返回结果。结果顺序可能与插入顺序一致,但不能保证并且不能依赖此行为(除了上限集合)。

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

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

如果使用索引怎么办?

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

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

封顶集合如何维护插入顺序?

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

于 2012-07-22T09:55:50.060 回答
9

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

于 2012-07-22T09:53:45.863 回答