2013-03-10 97 views
5

我有一個小副本組三個mongod的服務器(每個16GB RAM,至少4個CPU核心和真正的硬盤驅動器)和一個專門的仲裁機構。目前複製的數據約有100,000,000條記錄。幾乎所有這些數據都在一個集合中,索引號爲_id(自動生成的Mongo ID)和date,這是一個本地Mongo日期字段。我會定期刪除這個集合使用日期索引,這樣的事情(從蒙戈外殼)的舊記錄:MongoDB的速度很慢刪除

db.repo.remove({"date" : {"$lt" : new Date(1362096000000)}}) 

這並不工作,但它的運行速度非常,非常緩慢。其中一個節點的I/O比另外兩個節點慢,只有一個SATA驅動器。當這個節點是主節點時,刪除以大約5-10個文檔/秒運行。通過使用rs.stepDown()我已經降級了這個較慢的主服務器,並強制選舉來獲得具有更好I/O的主服務器。在該服務器上,我獲得大約100個文檔/秒。

我的主要問題是,我應該擔心嗎?我沒有引入複製之前的數字,但我知道刪除速度要快得多。我想知道副本集同步是否導致I/O等待,或者是否有其他原因。在刪除語句結束之前,我會很樂意暫時禁用同步和索引更新,但我目前還不知道有什麼辦法可以做到這一點。出於某種原因,當我禁用三個節點中的兩個節點時,只留下一個節點和仲裁器,剩下的節點將降級並且寫入不可能(不是仲裁者應該解決這個問題?)。

爲了讓您的一般性能的一些提示,如果我刪除並重新創建日期索引,大約需要15分鐘,掃描所有100M文檔。

+0

您無法禁用四個節點中的兩個的原因是,如果沒有大多數可用集合,則無法創建主節點。順便說一下,你爲什麼有四名成員?副本集中不需要具有三個節點的仲裁器。 – 2013-03-10 21:06:11

+0

Gotcha - 我目前只有四個節點,因爲第五個節點缺少硬盤驅動器,我將它從羣集中刪除了:)具有諷刺意味的是,我提出了一個仲裁器來幫助保證在大選中總會有一個勝利者。無論如何,仲裁器是一個小虛擬機,我也用於其他低成本的東西,比如其他分片集羣中的配置服務器。 – SteveK 2013-03-10 22:02:52

+0

當你有四個節點(有五張選票)時,你需要一個仲裁器,但是當你從副本集中刪除第五個節點時,你應該刪除仲裁器,這樣你將剩下三個成員。 – 2013-03-10 23:06:46

回答

7

發生這種情況,因爲即使

db.repo.remove({"date" : {"$lt" : new Date(1362096000000)}}) 

看起來像它的許多文件實際運行一個命令 - 多達滿足這個查詢。

當您使用複製時,每個更改操作都必須寫入名爲oplog.rslocal數據庫中的特殊集合 - 簡稱oplog。

的OPLOG必須爲每個已刪除文檔的條目,需要應用到OPLOG每個二次這些條目中的每一個之前它也可以刪除相同的記錄。

我建議您考慮的一件事是TTL indexes - 他們將根據您設置的過期日期/值「自動」刪除文檔 - 這樣您就不會有一次大規模刪除,而是可以分散負載隨着時間的推移。

+0

感謝您的解釋,這很有道理。我也不知道TTL索引 - 看起來像一個很棒的功能! – SteveK 2013-03-10 21:32:25

+0

我不確定這個解決方案是否準確。在https://docs.mongodb.org/manual/core/index-ttl/上的Mongo文檔中,它指出:「在副本集上,TTL後臺線程僅刪除主文檔,但TTL後臺線程運行次要成員從主要複製刪除操作。「那麼這是否意味着與手動操作相比,TTL的oplog性能沒有差別? – Nucleon 2016-03-16 18:39:55

+0

區別在於TTL線程每分鐘運行一次查找文件即可刪除。在這種情況下,用戶正在運行一次巨大的刪除,一次刪除它們。 TTL只是將刪除時間延長一段時間,因此您每分鐘都會執行較小的區塊。假設到期時間是「準確到分鐘」的字段。 – 2016-03-16 18:43:54

1

另一個建議可能不適合你,但對我來說是最佳的解決方案:從收集

  1. 下降的indeces
  2. 疊代的記錄,收集和存儲的ID的所有條目刪除到存儲陣列
  3. 每次數組足夠大(對我來說是10K記錄),我用的ID刪除這些記錄
  4. 重建的indeces

這是最快的方法,但它需要停止適合我的系統。