【发布时间】:2013-10-30 12:20:42
【问题描述】:
更新更新:
已解决!看到这个: MongoDB: cannot iterate through all data with cursor (because data is corrupted)
这是由损坏的数据集引起的。不是 MongoDB 或驱动程序。
================================================ ============================
我正在使用 MongoDB(2.4.6) 的最新 Java 驱动程序(2.11.3)。我有一个包含约 250M 记录的集合,我想使用游标来遍历所有记录。但是,大约 10 分钟后,我得到了一个错误的 cursor.hasNext(),或者说服务器上不存在游标的异常。
在那之后,我了解了光标超时并将我的 cursor.next() 包裹在 try/catch 中。如果有任何异常,或者 hasNext() 在遍历所有记录之前返回 false,程序将关闭游标并分配一个新游标,然后直接跳回上下文。
但后来我读到了有关 cursor.skip() 性能问题的信息……该程序刚刚达到了约 20M 记录,并且 cursor.next() 在 cursor.skip() 抛出“java.util.NoSuchElementException”之后。我相信这是因为跳过操作已经超时,导致光标无效。
是的,我已经阅读了有关 skip() 性能问题和光标超时问题的信息……但现在我认为我处于两难境地,修复一个会破坏另一个。
那么,有没有办法优雅地遍历庞大数据集中的所有数据?
@mnemosyn 已经指出我必须依赖基于范围的查询。但问题是我想把所有的数据分成16个部分在不同的机器上处理,而且数据在任何单调键空间内都不是均匀分布的。如果需要负载平衡,则必须有一种方法来计算特定范围内有多少键并对其进行平衡。我的目标是将它们分成 16 个部分,因此我必须找到键的四分位数(抱歉,我不知道是否有数学术语)并使用它们来拆分数据。
有没有办法做到这一点?
当通过获取分区边界键实现第一次搜索时,我确实有一些想法。如果新光标再次超时,我可以简单地记录最新的 tweetID 并使用新范围跳回。但是,范围查询应该足够快,否则我仍然会超时。我对此没有信心......
更新:
问题解决了!我没有意识到我不必以大块的方式对数据进行分区。循环作业调度员会做。请参阅已接受答案中的 cmets。
【问题讨论】:
-
为什么处理 100 条记录需要很长时间才能获得如此大的批次?您可以制作第 1 批文档,然后只要您能够在不到 10 分钟的时间内处理它,您就可以获得下一个批次/文档。见docs.mongodb.org/manual/reference/method/cursor.batchSize
-
我没有触摸 cursor.batchSize()。我只是封装了 100 条记录并将其推送到管道。我说“管道”是因为其中有 12 个,并且并行化使事情变得更快。不是我10分钟没碰光标。但相反,我一直在拉,拉,最后仍然超时。
-
@AsyaKamsky 看到这个:stackoverflow.com/questions/19649978/… 如果加快管道速度会有帮助,恕我直言,链接中的问题永远不会存在。
-
不是真的。问题是您对结果所做的工作,而不是获取结果的速度。
-
所以这和另一个问题是同一个问题?相同的损坏数据集?