MongoDB封顶集合上带过滤器的自然顺序
我有一个MongoDB capped集合,具有以下索引:MongoDB封顶集合上带过滤器的自然顺序,mongodb,Mongodb,我有一个MongoDB capped集合,具有以下索引: [ { "v" : 1, "key" : { "_id" : 1 }, "name" : "_id_", "ns" : "events.messageIn" }, { "v" : 1, "key" : { "uuid" : 1, "t
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "events.messageIn"
},
{
"v" : 1,
"key" : {
"uuid" : 1,
"ts" : -1
},
"name" : "uuid_1_ts_-1",
"ns" : "events.messageIn",
"background" : true
}
]
正如您可能推断的,这是一组事件数据。因为时间戳总是在增加,所以顺序{$natural:-1}
应该等同于顺序{ts:-1}
。我顺便在ts
上添加了一个索引,以便能够高效地查询时间片(例如db.messageIn.find({ts:{$gte:ISODate(“2016-08-01”)})
然而,我(也许是天真地)期望逻辑问题“给我一些最近的消息”将由db.messageIn.find({UUID:SOME_uid}).sort({$natural:-1})
最有效地回答。事实上,该查询是一个集合扫描,比db.event.find({UUID:SOME_uid})的计划慢几个数量级.sort({ts:-1})
这到底是为什么?推测一下,我假设这是因为MongoDB认为,一旦查看索引,它将无法提供自然顺序;因此,它回归到集合扫描。MongoDB是否有办法更聪明地处理此查询?例如,使用书籍索引的类比:
uuid ts page
abcdef 2016-06-01T00:03 10
abcdef 2016-06-01T00:02 8
abcdef 2016-06-01T00:01 6
ghijkl 2016-06-01T00:03 9
mnopqr 2016-06-01T00:02 7
mnopqr 2016-06-01T00:01 5
一旦通过uuid
进行过滤,您就可以很容易地按页面顺序进行排序;无需按顺序访问每个页面,检查其uuid,并在匹配时生成页面。MongoDB的“页面”是什么引用在某种程度上不可排序?很明显,我的心智模型在某些方面有缺陷。根据我对支持更高插入吞吐量的理解,capped collection不使用索引以插入顺序(或插入向后顺序)返回文档。因此,当db.messageIn.find({uuid:SOME_uid})时,排序({$natural:-1})执行
,逐个检查每个文档以保留插入顺序,并过滤匹配的文档
另一方面,db.event.find({uuid:SOME_uid}).sort({ts:-1})
要快得多,因为它使用“uuid_1_ts_uid-1”索引来匹配uuid和排序。在MongoDB中,排序操作可以通过根据索引中的顺序检索文档来获得排序顺序(这与您的情况非常相似)
顺便说一句,“uuid_1_ts_-1”不会在db.messageIn.find({ts:{$gte:ISODate(“2016-08-01”)})之类的查询中使用
由于它是一个复合索引,对于复合索引,MongoDB只能用于支持查询。根据我对支持更高插入吞吐量的理解,capped collection不使用索引以插入顺序(或插入向后顺序)返回文档。因此,当db.messageIn.find({uuid:SOME_uid})时({$natural:-1})
执行每个文档都会逐个检查以保留插入顺序,并过滤匹配的文档
另一方面,db.event.find({uuid:SOME_uid}).sort({ts:-1})
要快得多,因为它使用“uuid_1_ts_uid-1”索引来匹配uuid和排序。在MongoDB中,排序操作可以通过根据索引中的顺序检索文档来获得排序顺序(这与您的情况非常相似)
顺便说一句,“uuid_1_ts_-1”不会用于诸如db.messageIn.find({ts:{$gte:ISODate(“2016-08-01”)}}})之类的查询,因为它是一个复合索引,对于复合索引,MongoDB只能用于支持查询