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

时间:2018-04-10 17:48:25

标签: mongodb mongodb-query pymongo

我正在尝试通过单个字段对包含数百万行的集合进行完全排序。 据我所知,ObjectId包含4个字节的时间戳。而我的时间戳是4字节整数索引字段。所以我想按_id排序,时间戳应该是相似的,但这里是结果

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,

我致力于mongodb进程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 个答案:

答案 0 :(得分:0)

_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.

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

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

答案 1 :(得分:0)

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

来自Documentation的单词

  

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

我也尝试解释查询,并注意到使用_id完成排序时nscannedObjects和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
}

答案 2 :(得分:0)

指标的影响。

  

使用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/

相关问题