UUID rfc 4122(16バイト)がMongoDB ObjectId(12バイト)よりもはるかに大きいことを考慮して、それらの衝突確率がどのように比較されるかを調べようとしています。
私はそれが周りの何かであることを知っています非常にありそうもない、しかし私の場合、ほとんどのIDは限られたサーバーのセット内ではなく、多数のモバイルクライアント内で生成されます。 この場合、正当な懸念があるのだろうか。
すべてのIDが少数のクライアントによって生成される通常の場合と比較して:
私の場合、ほとんどのIDは、限られたサーバーセット内ではなく、多数のモバイルクライアント内で生成されます。この場合、正当な懸念があるのではないかと思います。
それは私にとって非常に悪いアーキテクチャのように思えます。 2層アーキテクチャを使用していますか?モバイルクライアントがデータベースに直接アクセスできるのはなぜですか?本当にネットワークベースのセキュリティに依存したいですか?
とにかく、衝突確率についてのいくつかの審議:
UUIDもObjectIdも、そのサイズに依存しません。つまり、どちらも乱数ではありませんが、衝突の可能性を体系的に削減しようとするスキームに従います。 ObjectIds、その構造は の場合:
これは、UUIDとは異なり、ObjectIdは単調である(1秒以内を除く)ことを意味します。これはおそらく最も重要なプロパティです。単調なインデックスを使用すると、Bツリーがより効率的に入力され、IDによるページングが可能になり、IDによる「デフォルトの並べ替え」が可能になり、カーソルが安定します。もちろん、タイムスタンプは簡単に抽出できます。これらはあなたが知っておくべき最適化であり、それらは巨大になる可能性があります。
他の3つのコンポーネントの構造からわかるように、単一のプロセスで1,000を超える挿入/秒を実行している場合(サーバーからでも不可能)、またはマシンの数が増える場合は、衝突が発生する可能性が非常に高くなります。約10を超えた場合(誕生日の問題を参照)、または単一のマシン上のプロセスの数が大きくなりすぎる場合(これらも乱数ではありませんが、マシン上では本当に一意ですが、2バイトに短縮する必要があります) )。
当然、衝突が発生するためには、これらの側面がallで一致する必要があるため、2つのマシンが同じマシンハッシュを持っている場合でも、それは必要です。まったく同じ秒と同じプロセスIDに同じカウンター値で挿入するクライアントですが、そうです、これらの値は衝突する可能性があります。
documentation から「ObjectId」の仕様を見てみましょう:
概要概要
ObjectIdは12バイトのBSONタイプであり、以下を使用して構築されます。
- unixエポックからの秒数を表す4バイトの値。
- 3バイトのマシンID、
- 2バイトのプロセスID、および
- ランダムな値で始まる3バイトのカウンター。
したがって、これを「モバイルクライアント」のコンテキストで考えてみましょう。
注:ここでのコンテキストはではなく「直接」接続を使用することを意味します「モバイルクライアント」のデータベースへの追加。それはすべきではありません。しかし、「_ id」の生成は非常に簡単に実行できます。
だからポイント:
「エポックからの秒数」の値。これは、リクエストごとにかなりランダムになります。そのため、そのコンポーネントだけに最小限の衝突の影響があります。 「秒」ではありますが。
「マシン識別子」。したがって、これはis異なるクライアントが_id
値を生成します。これにより、さらなる「衝突」の可能性が排除されます。
「プロセスID」。そのため、シードにアクセスできる場合(そしてアクセスできるはずです)、生成された_id
には、衝突を回避するmoreチャンスがあります。
「ランダム値」。したがって、別の「クライアント」はどういうわけか上記と同じ値をすべて生成し、stillは同じ値を生成することができましたランダムな値。
結論として、thatがダイジェストを行うのに十分な引数でない場合は、独自の「uuid」エントリを「主キー」値として指定するだけです。
しかし、私見、それは公正な説得力のある議論であり、ここでの衝突の側面は非常に広いと見なす必要があります。控えめに言っても。
fullトピックは、おそらく少し「広すぎる」です。しかし、これにより、検討が「まったくありそうもない」からもう少し具体的なものに移ることを願っています。