查询ETL的整个MongoDB集合的最佳方法

时间:2016-07-17 11:03:51

标签: mongodb etl

我们想要查询整个实时制作的MongoDB集合(v2.6,大约70M文档的大约500GB数据)。

我们想知道最好的方法是什么:

  1. 没有过滤的单个查询,可以打开游标并分批获取5 / 6k
  2. 的文档
  3. 使用find()。limit(5000).skip(currentIteration * 5000)
  4. 的逻辑进行分页。

    我们不确定什么是最佳做法,并且会产生最佳效果,而对性能的影响最小。

3 个答案:

答案 0 :(得分:1)

我会选择1.& 2.尽可能混合:在页面中迭代您的巨大数据集,但通过查询而不是跳过它们来访问这些页面,因为docs也指出这可能代价高昂。

  

cursor.skip()方法通常很昂贵,因为它需要   服务器从集合或索引的开头走到get   开始返回结果之前的偏移或跳过位置。作为   offset(例如上面的pageNumber)增加,cursor.skip()将成为   更慢,更密集的CPU。使用更大的集合,cursor.skip()   可能会成为IO界限。

因此,如果可能的话,在索引字段上构建页面并使用相应的查询范围处理这些批量数据。

答案 1 :(得分:1)

野蛮的方式

一般来说,大多数驱动程序无论如何都会加载批量文档。所以你的语言相当于

var docs = db.yourcoll.find()
docs.forEach(
  function(doc){
    //whatever
  }
)

实际上最初只是创建一个游标,然后,当当前批次接近耗尽时,将透明地加载一个新批次。因此,在计划访问集合中的每个文档时手动执行此分页几乎没有任何优势,但保留了多个查询的开销。

对于ETL,手动迭代文档进行修改然后将它们存储在新实例中在大多数情况下对我来说似乎不合理,因为你基本上重新发明了轮子。

替代方法

一般来说,没有一种适合所有“最佳”的方式。最好的方法是最适合您的功能和非功能需求。

从MongoDB到MongoDB进行ETL时,我通常按以下步骤进行:

ET ...

除非你有非常复杂的转换,MongoDB's aggregation framework是一个令人惊讶的ETL工具。我为此目的定期使用它,并且尚未发现使用MongoDB ETL的聚合框架无法解决的问题。鉴于通常每个文档都是逐个处理的,如果可以注意到,对生产环境的影响应该是最小的。完成转换后,只需使用$out stage将结果保存到新集合中。

使用$lookup stage即可实现跨越转换的集合。

...→

在对旧实例进行提取和转换后,为了将数据加载到新的MongoDB实例,您有以下几种可能性:

  1. 创建一个临时replica set,由旧实例,新实例和arbiter组成。确保您的旧实例成为主实例,执行ET部分,使主要步骤失效,以便新实例成为主实例,并从副本集中删除旧实例和仲裁器。优点是,您可以帮助MongoDB的复制机制将旧实例中的数据提供给新实例,而无需担心部分执行的传输等。你可以反过来使用它:首先传输数据,使新实例成为主要实例,从副本集中删除其他成员执行转换,然后删除“旧”数据。
  2. 使用db.CloneCollection()。这里的优点是您只需要转移所需的集合,但需要花费更多的手工工作。
  3. 使用db.cloneDatabase()复制整个数据库。除非原始实例上有多个数据库,否则此方法与副本集方法相比几乎没有优势。
  4. 正如所写,在不知道您的确切用例,转换和约束的情况下,很难说哪种方法对您最有意义。

答案 2 :(得分:1)

MongoDB 3.4支持并行收集扫描。我自己从未尝试过这个。但看起来很有趣。

这不适用于分片群集。如果我们有并行处理设置,这肯定会加快扫描速度。

请参阅此处的文档:https://docs.mongodb.com/manual/reference/command/parallelCollectionScan/