6

3つのmongodサーバー(それぞれ16GBのRAM、少なくとも4つのCPUコアと実際のHDD)と1つの専用アービターの小さなレプリカセットがあります。複製されたデータには、現在約1億件のレコードがあります。_idこのデータのほぼすべてが、 (自動生成されたMongo ID)とのインデックスを持つ1つのコレクションに含まれていdateます。これは、ネイティブのMongo日付フィールドです。定期的に、(mongoシェルから)次のような日付インデックスを使用して、このコレクションから古いレコードを削除します。

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

これは機能しますが、実行速度は非常に遅くなります。私のノードの1つは他の2つよりもI/Oが遅く、SATAドライブが1つだけです。このノードがプライマリの場合、削除は約5〜10ドキュメント/秒で実行されます。rs.stepDown()を使用することにより、この遅いプライマリを降格し、より良いI/Oを備えたプライマリを取得するための選択を強制しました。そのサーバーでは、約100ドキュメント/秒を取得しています。

私の主な質問は、私は心配する必要がありますか?レプリケーションを導入する前の番号はありませんが、削除がはるかに高速であったことはわかっています。レプリカセットの同期がI/O待機を引き起こしているのか、それとも他の原因があるのか​​疑問に思っています。削除ステートメントが終了するまで、同期とインデックスの更新を一時的に無効にすることは完全に満足ですが、現時点ではそれを行う方法がわかりません。何らかの理由で、3つのノードのうち2つを無効にして、1つのノードとアービターだけを残すと、残りのノードが降格され、書き込みが不可能になります(アービターはそれを解決するはずではありませんか?)。

一般的なパフォーマンスを示すために、日付インデックスを削除して再作成すると、1億のドキュメントすべてをスキャンするのに約15分かかります。

4

2 に答える 2

12

これが起こっているのは

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

単一のコマンドのように見えますが、実際には多くのドキュメントで動作しています。このクエリを満たすものと同じ数です。

レプリケーションを使用する場合、すべての変更操作は、データベース内の-略してoploglocalと呼ばれる特別なコレクションに書き込まれる必要があります。oplog.rs

oplogには、削除されたドキュメントごとにエントリが必要です。同じレコードを削除する前に、これらのエントリのすべてを各セカンダリのoplogに適用する必要があります。

TTLインデックスを検討することをお勧めします。TTLインデックスは、設定した有効期限/値に基づいてドキュメントを「自動的に」削除します。これにより、大規模な削除が1回行われることはなく、時間の経過とともに負荷を分散できるようになります。 。

于 2013-03-10T21:04:48.727 に答える
2

あなたに合わないかもしれない別の提案ですが、それは私にとって最適な解決策でした:

  1. コレクションからindecesを削除します
  2. コレクションのすべてのエントリを反復処理し、レコードのIDを格納してメモリ配列に削除します
  3. 配列が十分に大きい(私にとっては10Kレコードでした)たびに、これらのレコードをIDで削除しました
  4. indecesを再構築します

最速の方法ですが、システムを停止する必要があり、私には適していました。

于 2014-06-06T15:58:36.313 に答える