web-dev-qa-db-ja.com

MongoDBおよび複合主キー

私は、mongo dbで複合主キーを処理する最良の方法を決定しようとしています。このシステムのデータを操作するための主なキーは、2つのuuidで構成されています。 uuidの組み合わせは一意であることが保証されていますが、個々のuuidはいずれも一意ではありません。

これを管理する方法がいくつかあります。

  1. 2つの値で構成される主キーのオブジェクトを使用します(提案されているように here

  2. 標準の自動生成mongoオブジェクトIDを主キーとして使用し、キーを2つの別々のフィールドに保存してから、これら2つのフィールドに複合インデックスを作成します

  3. 主キーを2つのuuidのハッシュにする

  4. 私が現在気づいていない他のいくつかの素晴らしいソリューション

これらのアプローチのパフォーマンスへの影響は何ですか?

オプション1では、非順次キーがあるために挿入のパフォーマンスが心配です。これにより、従来のRDBMSシステムが停止する可能性があることを知っています。また、MongoDBでもこれが当てはまるという兆候を見てきました。

オプション2の場合、システムで使用されることのない主キーを持つことは少し奇妙に思えます。また、クエリパフォーマンスはオプション1ほど優れていないようです。従来のRDBMSでは、クラスター化インデックスが最適なクエリ結果を提供します。 MongoDBでこれはどの程度関連していますか?

オプション3の場合、これは1つの単一のidフィールドを作成しますが、再び挿入するときは連続しません。このアプローチに他の長所/短所はありますか?

オプション4の場合...オプション4とは何ですか?

また、将来のある時点でMongoDBの代わりにCouchDBを使用する可能性についての議論もあります。 CouchDBを使用すると、別のソリューションが提案されますか?

詳細:問題に関する背景を見つけることができます ここ

45
herbrandson

オプション1を選択してください。

主な理由は、パフォーマンスが心配だということです。常に存在し、既に一意である_idインデックスを使用すると、2番目の一意のインデックスを維持する必要がなくなります。

オプション1の場合、非シーケンシャルキーを使用した場合の挿入パフォーマンスが心配です。これにより、従来のRDBMSシステムが停止する可能性があることを知っています。また、MongoDBでもこれが当てはまるという兆候を見てきました。

他のオプションはこの問題を回避せず、単に_idインデックスからセカンダリユニークインデックスにシフトしますが、2つのインデックスが作成されます。

オプション1を疑問視する理由は1つだけです。これは、1つまたは他のUUID値のみでドキュメントにアクセスする場合です。常に両方の値を提供し、(この部分は非常に重要です)すべてのクエリで常に同じ方法で順序付けている限り、_idインデックスはその完全な目的を効率的に果たします。

サブドキュメント{ a:1, b:2 }{ b:2, a:1 }と等しくない場合、2つのUUID値を常に同じ方法で順序付けする必要があることの詳細については、2つのドキュメントにそれらの値が含まれているコレクションを作成できます。 _id。したがって、フィールド_idを最初に格納する場合、すべてのドキュメントとクエリで常にその順序を維持する必要があります。

もう1つの注意点は、_id:1のインデックスがクエリに使用できることです。

db.collection.find({_id:{a:1,b:2}}) 

しかし、それはnotクエリに使用可能です

db.collection.find({"_id.a":1, "_id.b":2})
39
Asya Kamsky

私にはあなたのためのオプション4があります:

自動_idフィールドを使用し、単一の複合インデックスではなく、両方のuuidに2つの単一フィールドインデックスを追加します。

  1. _idインデックスはシーケンシャルになり(MongoDBではそれほど重要ではありませんが)、簡単にシャーディングでき、MongoDBに管理させることができます。
  2. 2つのuuidインデックスを使用すると、必要な種類のクエリ(最初のクエリ、2番目、または両方の順序)を作成でき、1つの複合インデックスよりも少ないスペースを使用します。
  3. 同じクエリで両方のインデックス(および他のインデックス)を使用する場合、MongoDBは複合インデックスを使用しているかのように 交差 (v2.6の新機能)になります。
6
i3arnon

私は2つのオプションに行きますが、理由があります

  1. 1番目に提案されたように両方のuuidから連結されたフィールドの代わりに2つの別個のフィールドがあると、将来のクエリ要求をサポートするためにインデックスの別の組み合わせを作成したり、判明した場合、あるキーのカーディナリティが別のキーよりも高いという柔軟性が得られます。
  2. 連続キーを持たないことは、シャード環境に挿入する際のホットスポットを回避するのに役立つ可能性があるため、それほど悪いオプションではありません。書き込みロックはデータベースレベル(2.6より前)またはコレクションレベル(2.6バージョン)であるため、シャーディングは、コレクションに対する挿入と更新をスケーリングする最良の方法です。
4
Boris

オプション2を選択します。両方のUUIDフィールドを処理するインデックスを作成することができ、パフォーマンスは複合プライマリキーと同じである必要がありますが、操作がはるかに簡単になります。

また、私の経験では、厳密に必須ではない場合でも、何か一意のIDを与えたことを後悔したことはありません。おそらくそれは不人気な意見でしょう。

2
Brent