簡體   English   中英

查詢ETL的整個MongoDB集合的最佳方法

[英]Best way to query entire MongoDB collection for ETL

我們想要查詢整個實時制作MongoDB集合(v2.6,大約70M文檔的大約500GB數據)。

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

  1. 沒有過濾的單個查詢打開游標並以5 / 6k的批量獲取文檔
  2. 使用find()。limit(5000).skip(currentIteration * 5000)的邏輯進行分頁迭代。

我們不確定什么是最佳實踐,並且會以最小的性能影響產生最佳結果。

如果可能,我會選擇1.&2.混合:在頁面中迭代您的大數據集,但通過查詢而不是跳過它們來訪問這些頁面,因為這可能是昂貴的,正如文檔所指出的那樣。

cursor.skip()方法通常很昂貴,因為它要求服務器從集合或索引的開頭走,以在開始返回結果之前獲取偏移或跳過位置。 隨着偏移量(例如上面的pageNumber)的增加,cursor.skip()將變得更慢並且CPU密集度更高。 對於較大的集合,cursor.skip()可能會成為IO綁定。

因此,如果可能的話,在索引字段上構建頁面,並使用相應的查詢范圍處理這些批量數據。

殘酷的方式

一般來說,大多數驅動程序無論如何都會加載批量文檔。 所以你的語言相當於

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

實際上只是最初創建一個游標,然后,當當前批次接近耗盡時,將透明地加載一個新批次。 因此,在計划訪問集合中的每個文檔時手動執行此分頁幾乎沒有任何優勢,但要保留多個查詢的開銷。

對於ETL,手動迭代文檔進行修改然后將它們存儲在新實例中在大多數情況下對我來說似乎不合理,因為你基本上重新發明了輪子。

替代方法

一般來說,沒有一種尺寸適合所有“最佳”方式。 最好的方法是最適合您的功能和非功能需求的方法。

從MongoDB到MongoDB進行ETL時,我通常按如下方式進行:

ET ...

除非你有非常復雜的轉換,否則MongoDB的聚合框架是一個令人驚訝的ETL工具。 我為此目的定期使用它,並且尚未發現使用MongoDB ETL的聚合框架無法解決的問題。 鑒於通常每個文檔都是逐個處理的,如果可以注意到,對生產環境的影響應該是最小的。 完成轉換后,只需使用$out階段將結果保存到新集合中。

甚至可以使用$lookup階段實現跨越轉換的集合。

... ...你

在對舊實例進行提取和轉換之后,為了將數據加載到新的MongoDB實例,您有以下幾種可能性:

  1. 創建臨時副本集 ,包括舊實例,新實例和仲裁服務器 確保您的舊實例成為主實例,執行ET部分,使主要步驟失效,以便新實例成為主實例,並從副本集中刪除舊實例和仲裁器。 優點是,您可以幫助MongoDB的復制機制將舊實例中的數據提供給新實例,而無需擔心部分執行的傳輸等。 您可以反過來使用它:首先傳輸數據,使新實例成為主要實例,從副本集中刪除其他成員執行轉換並刪除“舊”數據。
  2. 使用db.CloneCollection() 這里的優點是您只需轉移所需的集合,但需要花費更多的手動工作。
  3. 使用db.cloneDatabase()復制整個數據庫。 除非原始實例上有多個數據庫,否則此方法與副本集方法相比幾乎沒有優勢。

如上所述,在不知道您的確切用例,轉換和約束的情況下,很難說哪種方法對您最有意義。

MongoDB 3.4支持並行收集掃描。 我自己從未嘗試過這個。 但看起來很有趣。

這不適用於分片群集。 如果我們有並行處理設置,這肯定會加快掃描速度。

請參閱此處的文檔: https//docs.mongodb.com/manual/reference/command/parallelCollectionScan/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM