web-dev-qa-db-ja.com

MongoDB:更新/更新と挿入

最近、複数のアップサートの実行( 一括操作 )と挿入(複数のドキュメント)のパフォーマンスの大きな違いに気付きました。私はこれに正しくなっているかどうかを知りたい:

  • 更新/更新はfind()およびupdate()のようになるため、読み取りと書き込みの2つのことを行います
  • 挿入するだけで書き込みが速くなります

したがって、パフォーマンスの違いは?

この場合、ドキュメントを更新する代わりに、createdOnフィールドを使用して新しいドキュメントを作成するために、定期的に大量の書き込みが必要かどうか疑問に思います。次に、クエリを実行するには、createdOn DESCでソートされたドキュメントをクエリします。これは良い方法でしょうか?または、より良い方法はありますか?

  • コレクションにインデックスがあるかどうかは疑問ですが、更新を高速化できますか?しかし、このインデックスは書き込み部分を遅くしませんか?
  • 挿入のみを行う第2の方法では、ドキュメントが多すぎるので速度が低下しますか? (書き込みを高速化するために)実用的ですか?
  • 接続プールのサイズを増やしてみました。何が最適かはわかりませんが、20個を試しましたが、mongostatを使用して1秒あたり20個のクエリを処理できます。私はそれがもっと高くなると思った。
15
Jiew Meng

ドキュメントを挿入する場合、Mongodbは同じobjectIdを持つドキュメントが存在するかどうかを確認する必要があります。そのドキュメントが存在する場合は挿入できません。

同じケースがアップデートに適用されます。ドキュメントが存在するかどうかを確認する必要があります。そうでない場合、更新を実行できません。 ObjectId/Indexedフィールドに基づいてドキュメントが見つからない場合、更新クエリが遅くなるケース。

その他のドキュメントの挿入/更新のパフォーマンスは同じである必要があります。

例えば.....

したがって、Insertは次のようになります//(Fast)

  1. (ドキュメントを確認->見つかりません->新しいドキュメントを挿入)その他
  2. (ドキュメントの確認->見つかった->挿入できません)

そしてupsertで更新(ObjectIdが利用可能)//(高速)

  1. (ドキュメントを確認->見つかりません->新しいドキュメントを挿入)その他
  2. (ドキュメントの確認->見つかった->ドキュメントの更新)

またはupsert(ObjectIdなし)//これは遅い

  1. (ObjectIdの検索(遅い)->見つかりません->新しいドキュメントの挿入)その他
  2. (ObjectIdの(遅い)->見つかった->ドキュメントを更新します)
20
Code OverFlow

MongoDBでupsertがどのように機能するかについての「公式」説明は見つかりませんでしたが、操作は既存のドキュメントの更新を目的としており、ドキュメントが指定された基準が見つかりません。

インデックスを追加すると、upsertが高速になります。すべてのインデックスを使用してドキュメントを「検索」した後です。警告は、インデックスが動作するフィールドと更新するフィールドにあります。更新された部分がインデックスの一部である場合、ドキュメントの更新にパフォーマンスの影響があります。更新された部分がインデックスの一部ではない場合、既存のドキュメントへの書き込みに対してペナルティは発生しません。ただし、ドキュメントが追加されると、インデックスコレクションが更新されるため、パフォーマンスにわずかな影響があります。それでも、ドキュメントを追加するだけで高速になります。

したがって、シナリオでドキュメントを更新したくないことがわかっている場合、挿入は一般的に高速です。同じドキュメントを2回追加しないようにする場合は、一意のインデックスを追加することもできます。その後、挿入は失敗します。

全体的には特定のシナリオに依存しますが、質問から抽出できる情報に基づいて、ドキュメントを単に挿入することが最良の選択肢だと思います。 「createdon」フィールドを使用すると、シナリオ内でドキュメントが一意になるようにするので、読み取りシナリオで使用されるインデックスのみを考慮する必要があります。

MongoDB サイトでいくつかの追加情報を見つけることができます:

(読み取り)インデックスの設計の詳細については、インデックスがクエリプランに何かを追加するかどうかを確認するためのかなり良い説明があります here

これがお役に立てば幸いです。