【发布时间】:2013-11-06 00:02:15
【问题描述】:
我正在考虑将时间序列数据捆绑到会话文档中。在每个会话中,都会有一系列事件。每个事件都有一个时间戳。我知道我可以在这些事件的时间戳上创建一个多键索引,但我很好奇 MongoDB 使用什么机制来防止同一文档在一个查询中出现两次。
为了澄清,想象一下包含以下文档的会话集合:
{
_id: 'A',
events: [
{time: '10:00'},
{time: '15:00'}
]
}
{
_id: 'B',
events: [
{time: '12:00'}
]
}
如果我用db.sessions.ensureIndex({'events.time' : 1}) 添加一个多键索引,我希望该索引的 b 树看起来像这样:
'10:00' => 'A'
'12:00' => 'B'
'15:00' => 'A'
如果我使用{'events.time': {$gte: '10:00'}} 查询集合,MongoDB 会扫描 b-tree 并返回:
{ "_id" : "A", "events" : [ { "time" : "10:00" }, { "time" : "15:00" } ] }
{ "_id" : "B", "events" : [ { "time" : "12:00" } ] }
Mongo 如何防止文档A 第二次显示为光标中的第三个结果?对于小型索引扫描,它可以只跟踪已经查看过哪些文档,但是如果索引很大,会发生什么?是否有过同一个文档在单个光标中出现多次的情况?
我的假设是它不会。 Mongo 可以查看它正在扫描的文档,并通过检查索引数组中较早的条目来检测它已经在扫描中较早地匹配。但是,我在 MongoDB 文档中找不到任何提及此行为的内容,因此真正了解会发生什么很重要。
(注意:我确实知道如果在扫描光标时修改了文档,则文档可能会多次出现在单个查询中。这不应该构成查询从不编辑时间戳的时间序列数据的问题。即使在扫描期间将新事件添加到会话中,如果 Mongo 使用类似于我上面提到的检测机制,它应该能够省略移动的文档来自查询结果。)
【问题讨论】:
-
有趣的问题,但是如果索引大小很大,那么查询优化器将更喜欢集合扫描(BasicCursor),因为它的 nscanned 会更低。
-
不一定。我可能只扫描 1 个月的数据,其中可能包含大量会话,但仍远少于集合中的总会话数。在这种情况下,您肯定希望 Mongo 使用索引。