MongoDB查询不存在字段的记录和索引

4
我们有一个Mongo数据库,大约有100万个文档,我们想使用处理过的字段轮询此数据库,以查找我们之前未见过的文档。为此,我们正在设置一个名为_processed的新字段。
为了查询需要处理的文档,我们查询没有此处理字段的文档:
db.stocktwits.find({ "_processed" : { "$exists" : false } })

然而,每次执行此查询需要大约30秒的时间,速度相对较慢。在_processed字段上存在一个(asc)索引:
db.stocktwits.ensureIndex({ "_processed" : -1 },{ "name" : "idx_processed" });

添加此索引不会改变查询性能。集合中还有其他几个索引(即ID idx和每个文档中几个字段的唯一索引)。
_processed字段很长,也许应该将其更改为bool类型以加快速度?
我们尝试使用$where查询(即$where : this._processed==null)来执行与$exists : false相同的操作,性能大约相同(比$exists慢几秒,这是有道理的)...
是否有任何想法是什么导致了缓慢的性能(或者这是正常的)?有人对如何提高查询速度有任何建议吗?
干杯!

在创建文档时,将_processed字段设置为“false”不是一个选项吗? - Ian Mercer
谢谢留言。那应该是可行的(但作为最后的手段) - 我想避免这种情况,因为转储过程是优化过的。在这种情况下,_processed 字段是一个长整型,所以我们只需要将它设置为类似于 0 或 -1 的值。不过这是个好点子,如果将 processed 字段类型更改为布尔型是否会使事情更快呢?processed 只是存储了处理时间戳(仅用于帮助调试),但实际上它可以被设置为布尔型,如果我们真的需要,我们可以有 _processed(布尔型)和 _porcessed_timestamp(长整型)。 - NightWolf
2个回答

5

有趣,我不知道这个。好知道! - Cody Caughlan
2
同上,不知道这个(认为在这种时候有一个重要的教训,再次仔细阅读RTFM)。谢谢,解决了我的问题。只需将查询更改为{'_processed':null}。天才DV87! - NightWolf
现在运行,查询只需要8毫秒。太棒了! - NightWolf

4

因为检查 _processed -> not exists 没有提供很多选择性,所以速度会变慢。这就像在“性别”上建立索引一样-由于只有两个可能的选项 malefemale,如果您有 1M 行和一个在 Gender 上的索引,它将不得不扫描50%或500K行才能找到所有男性。

您需要使您的索引更具选择性。


谢谢你的评论,Cody。我理解你的观点,在Mongo中,所有空字段都被索引了。因此,如果我的数据集大多数已经处理过了,那么扫描起来并不那么糟糕,这比每个文档都要扫描要好。即使我将_processed = false,实际上_processed = false或_processed = null在很大程度上是等效的。 - NightWolf
我认为这与问题无关。MongoDB使用游标返回结果。只要值被索引,就没有“扫描”,结果可以像你抓取它们一样快速地流回来。问题在于搜索没有使用索引。 - Ian Mercer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接