当前位置: 首页 > 知识库问答 >
问题:

为什么 mongodb 按_id排序比按任何其他索引字段排序快得多?

云隐水
2023-03-14

我正试图通过单个字段对一个包含数百万行的集合进行完全排序。据我所知,ObjectId包含4个字节的时间戳。我的时间戳是4字节整数索引字段。所以我认为sort by _id和timestamp应该是相似的,但是下面是结果

db.coll.find().sort("_id", pymongo.ASCENDING)
# takes 25 minutes to run

db.coll.find().sort("timestamp", pymongo.ASCENDING)
# takes 2 hours to run

为什么会发生这种情况,这里有优化的方法吗?谢谢

更新

正如我指出的,我试图排序的时间戳字段已经被索引

馆藏统计

"size" : 55881082188,
"count" : 126048972,
"avgObjSize" : 443,
"storageSize" : 16998031360,
"capped" : false,
"nindexes" : 2,
"totalIndexSize" : 2439606272,

我致力于mongob进程4gb的ram(试图增加到8gb,但速度没有增加)

更新2

事实证明,有多少字段顺序排序遵循插入(自然)顺序,因此排序速度更快

我试图

db.new_coll.create_index([("timestamp", pymongo.ASCENDING)])
for el in db.coll.find().sort("timestamp", pymongo.ASCENDING):
    del el['_id']
    db.new_coll.insert(el)

# and now
db.new_coll.find().sort("timestamp", pymongo.ASCENDING)
# takes 25 minutes vs 2 hours as in previous example

共有3个答案

曹均
2023-03-14

索引。

当使用MongoDB sort()方法时,可以为结果集指定排序顺序——升序(1)或降序(-1)。如果没有对排序字段进行索引,MongoDB将在查询时对结果进行排序。查询时排序会占用CPU资源,并延迟对应用程序的响应。但是,当一个索引包含了所有用于选择和排序结果集的字段时,MongoDB不需要在查询时进行排序。相反,结果已经在索引中排序,并且可以立即返回。

请在此处查看更多详细信息。https://mobile.developer.com/db/indexing-tips-for-improving-your-mongodb-performance.html

https://docs . MongoDB . com/manual/tutorial/sort-results-with-indexes/

洪成济
2023-03-14

_id字段是自动创建的,它在将文档插入MongoDB数据库集合时存储一个12字节的ObjectId值,表示属于集合的BSON文档的唯一值。

根据MongoDB的文档

The 12-byte ObjectId value consists of:

a 4-byte value representing the seconds since the Unix epoch,
a 3-byte machine identifier,
a 2-byte process id, and
a 3-byte counter, starting with a random value.

在集合的字段上定义的索引加速了存储在数据库集合中的数据的检索过程,因为属于索引字段的值被排序为特定的排序顺序,并且一旦找到匹配值就停止扫描文档,从而最小化要扫描的文档数量。

在创建集合期间,在_id字段上定义了唯一索引,因此,按_id字段对数据进行排序有助于从集合中快速检索数据。

丌官昊天
2023-03-14

由于字段值的生成方式,按_id排序速度更快_id。

文档中的单词

驱动程序以上述方式生成ObjectId的主要原因之一是,由于排序的工作方式,它包含一个有用的行为。鉴于它包含一个4字节的时间戳(秒的分辨率)和一个递增计数器以及一些更独特的标识符,如机器ID一次,可以使用_id字段按创建顺序对文档进行排序,只需在_id字段上进行排序。如果您希望跟踪文档的创建时间,这对于节省额外时间戳所需的空间很有用。

我还尝试解释查询,并注意到当使用_id完成排序时,nscannedObject和nscannedObjectsAllPlans为0。

> db.coll.find({},{_id:1}).sort({_id:1}).explain();
{
        "cursor" : "BtreeCursor _id_",
        "isMultiKey" : false,
        "n" : 353,
        "nscannedObjects" : 0,
        "nscanned" : 353,
        "nscannedObjectsAllPlans" : 0,
        "nscannedAllPlans" : 353,
        "scanAndOrder" : false,
        "indexOnly" : true,
        "nYields" : 2,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "_id" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ]
        },
        "server" : "server",
        "filterSet" : false
}
 类似资料:
  • 问题内容: 我有一个用户模型和一个提交模型。每个提交都有一个上载用户的外键字段user_submitted。 我的问题很简单:如何获得提交量最多的三个用户的列表? 我尝试在用户模型上创建num_submissions方法: 然后执行: 但这失败了,就像我尝试过的所有其他尝试一样。我实际上可以使用智能数据库查询吗?还是我应该在视图文件中做些更怪异的事情? 问题答案: 你没有在示例模型代码中提及,但在

  • 问题内容: 我有一本字典,其中包含以下数据: 我想按double值对字典排序。我做了一些研究,但所有示例均不支持当前版本的Swift 我试过在Swift中按值使用SortDictionary中的这段代码: 但这是行不通的。如何按字典值对字典排序? 问题答案: 目前尚不清楚您的期望是什么。确实没有排序字典这样的东西。您的代码基本上是正确的,但括号位置错误。我尝试了这个: 结果: 如果您认为这是错误的

  • 问题内容: 我如何对数组进行排序: 数组结构可能类似于: 那么数据是根据数组的 标题字段* 以 ASC顺序 显示的吗? * 问题答案: 为此使用显式构建的用途。

  • 好吧,我有以下几个Shemas: 我想要的是让用户跟踪品牌,按品牌名排序,所以对于这样做,我对FollowAction进行查询,找到用户所做的所有FollowAction,然后填充brand字段。 所以问题是我不能为品牌名的查询排序,我知道的唯一方法是返回所有文档并从nodejs应用程序中对它们进行排序。有人知道我怎么能那样做吗??或者我是否应该改变shema结构?? 我所做的查询是:

  • 问题内容: 假设我有一些Schema,其中有一个像这样的虚拟字段 在查询中是否可以按虚拟字段对结果进行排序?就像是 当我尝试此操作时,结果很简单,无法排序… 问题答案: 您将无法按虚拟字段进行排序,因为它们没有存储到数据库中。 虚拟属性是很方便使用的属性,但不会持久存在于mongodb中。 http://mongoosejs.com/docs/2.7.x/docs/virtuals.html

  • 我已经在链接中看到了(http://bigocheatsheet.com/)插入排序的复杂性与冒泡排序相同,堆排序也优于这两种排序。但是,当我创建一个示例程序并比较插入排序所花费的时间时,我感到难以置信。 类用于测试排序算法。 泡泡排序类 用于插入排序的类 堆排序类 用于创建数组的类 我尝试了所有的情况,比如最好的情况、最坏的情况和一般情况。但在所有情况下,插入排序都比冒泡排序和堆排序快得多。理论