在庞大的 mongodb 集合中快速搜索非常稀有的字段
Posted
技术标签:
【中文标题】在庞大的 mongodb 集合中快速搜索非常稀有的字段【英文标题】:quickly search for very rare field in a huge mongodb collection 【发布时间】:2016-12-12 10:13:52 【问题描述】:我有大约 10 亿个文档的庞大集合,其中很少有文档(少于 200 个)包含某些字段“rare_field
”。
我怎样才能尽快找到包含该字段的所有文档?
如果我只是这样做:
collection.find( "rare_field" : $exists : true )
超时。 这可能需要几天时间才能完成,所以我不确定即使通过查询标志防止超时也会有所帮助,但也许我错了。
我也可以编写一个脚本来检查所有文档,但这会很慢,因为它需要通过网络将所有 10 亿个文档传递到我的服务器,我想要一些不需要任何数据传递的解决方案电线,而且会很快。
注意:这是一个sharded
集合。
我将发布我当前的解决方案作为答案,但我不确定它是否 100% 正确,而且速度没有我想要的那么快。
【问题讨论】:
将此rare-field
放入您的分片查询中!正因为如此,mongo 也会索引这个字段!所以它会很快!
谢谢。这是一次性的事情,所以我在这里并不需要索引。当数据库为空时,这可能是一个很好的解决方案,但是现在索引这个字段会花费很多时间,就像手动浏览所有文档一样(我认为)
你说的时间消耗是对的!所以这完全取决于你的应用程序!另一种方法是将结果保存在缓存中!将结果存储在新集合或 redis 或 smtn 中!
创建sparse index?
【参考方案1】:
如果没有rare-field
上的索引,在最坏的情况下,mongodb 将需要遍历集合中的所有文档。在这种情况下,光标可能会超时,因此您需要为光标添加一个标志以防止它这样做。
在 mongo shell 中,这意味着如下查询:
var cursor = db.collection.find( "rare_field" : $exists : true ).noCursorTimeout();
如果您担心网络问题或其他问题会在光标填充batchSize匹配文档之前中断查询,那么您确实可以按照您在答案中的建议逐一获取文档,但是您需要按 _id: 1
排序,并使用noCursorTimeout()
和limit(1)
,即:
var doc = db.collection.find( "rare_field" : $exists : true )
.sort( _id: 1 )
.limit(1)
.noCursorTimeout()
.next();
然后按照您的建议,通过重复查询来检索下一个文档,同时将条件 _id: $gt: doc._id
添加到查询对象。
【讨论】:
【参考方案2】:一个可能的解决方案是使用findOne
而不是find:
var doc = collection.findOne( "rare_field" : $exists : true );
然后循环获取下一个:
var doc = collection.findOne( _id : $gt : doc._id, "rare_field" : $exists : true );
但是,我不能 100% 确定这些调用是否必须给我按 _id
排序的结果,我也不确定单个 findOne
是否也不会超时。
我担心显式添加 sort(_id : 1)
会强制查询获取所有结果,然后传递第一个结果。
【讨论】:
我认为这不是一个好主意!就像你在做最糟糕的事情一样!你是 mongo 会做和find( "rare_field" : $exists : true );
一样的事情!但是您将其分成几部分,开销很大!
你的恐惧也解释了为什么你不应该这样做!:)以上是关于在庞大的 mongodb 集合中快速搜索非常稀有的字段的主要内容,如果未能解决你的问题,请参考以下文章