2015-10-14 62 views
4

每當我們使用collection.remove()從MongoDB中刪除大量數據時,這會使數據庫變得太慢,導致我們的Web服務器最終停止運行。我相信這是因爲刪除操作鎖定收集更長的時間。如何從MongoDB中刪除數據而不放慢速度?

我們有一個查詢,給我們所有我們想要刪除的文件。但是查詢不包含日期/時間字段,所以我們不能使用TTL索引。

有沒有辦法以nice的方式刪除數據,不時解鎖?

+0

我的哈克解決方案:編寫一個程序,查詢您想要刪除的所有文檔的ID,並將它們存儲在數組/列表中。然後爲它們中的每一個發出刪除命令。但是這很慢 –

+0

這是否過期?文件是否有某種日期字段? –

+0

不幸的是,他們沒有,否則我會使用TTL指數。這更多的是移民事宜。 –

回答

9

使用批量操作

批量操作可能一定的幫助。無序bulk.find(queryDoc).remove()基本上是爲大量操作優化的db.collection.remove(queryDoc)版本。它的用法很簡單:

var bulk = db.yourCollection.initializeUnorderedBulkOp() 
bulk.find(yourQuery).remove() 
bulk.execute() 

有關詳細信息,請參閱Bulk.find().remove() in the MongoDB docs

這種方法背後的想法不是加快清除速度,而是減少負載。在我的測試中,負載減少了一半,花費的時間比db.collection.remove(query)略少。

創建索引

但是,刪除操作不應該您的實例陳舊的凍結點。我在5歲的MacBook上測試了12M文檔的刪除,並且在它上面加載了一些內容,但它距離冰點很遠,花了大約10分鐘。但是,我用來查詢的字段是索引的。

這使我得出結論,可能您正在體驗收集掃描。如果我是對的,則會發生以下情況:您的查詢包含未包含在索引中的字段或字段的組合,或者索引交集無法構建的字段的組合。這迫使有問題的mongod從數據庫中查找,訪問並讀取這些字段,以便從數據庫中讀取每個文檔。

因此,在刪除操作之前在後臺創建包含查詢中每個字段的索引可能會很有幫助,但這是違反直覺的。

db.collection.createIndex(
    {firstFieldYouQueryBy:1,...,NthFieldYouQueryBy:1}, 
    {background:true} 
) 

儘管此操作將在後臺完成,但shell會阻塞。 這可能需要一段時間。您可以通過打開第二個外殼和使用查看狀態:

db.currentOp() 

(你必須搜索了一下)。

創建索引時(可以使用db.collection.getIndices()進行檢查),刪除操作應該更高效,因此速度更快。大規模刪除完成後,您當然可以刪除索引,否則不需要。

使用索引,可以防止收集掃描,從而大大加快刪除速度。

結合這兩種方法

應該是顯而易見的,這是有道理的後指數是準備先創建索引併發出大宗命令。

+0

嘿馬庫斯,感謝您的詳細解答!你是對的,我們的查詢沒有使用索引。但是,在我們的活動副本集上創建索引也是一個問題,它也會凍結我們的Web應用程序服務器:-(因此,我們不能只創建一個索引,我們必須逐個從副本集中移除每個節點,離線創建索引,並將其重新附加到副本集,這似乎是一個很大的努力,只是爲了刪除一些文檔,而且這涉及到一個新的主節點的選舉,這意味着數據庫有效地停頓了幾秒鐘。 –

+0

@BastianVoigt通過Skype聯繫你,我認爲有必要談談 –

+0

對不起,我停止使用Skype,因爲他們還沒有64位的Linux版本。在郵件中發送郵件bei bastian minus,voigt punkt de。 –

相關問題