135

NoSQL KVP またはドキュメント データベースの外部キーとインデックスに相当するものを見つけようとしています。(2 つのオブジェクト間の関係をマークするキーを追加するための) ピボット テーブルがないため、通常の Web ページに役立つ方法でデータを取得する方法について、私は本当に困惑しています。

ユーザーがいて、このユーザーがサイト全体に多くのコメントを残しているとします。ユーザーのコメントを追跡するために私が考えることができる唯一の方法は、

  1. それらをユーザーオブジェクトに埋め込みます(これはまったく役に立たないようです)
  2. user_id:comments必要に応じて取得できるように、各コメントのキー [コメント:34、コメント:197 など...] のリストを含む値を作成して維持します。

ただし、2 番目の例を取り上げると、3000 万の ID を含む可能性のある「active_comments」と呼ばれるキーなどの他のものを追跡するために使用すると、すぐにレンガの壁にぶつかり、最近のいくつかを知るためだけに各ページをクエリするのに TON の費用がかかります。活発なコメント。また、多くのページが同時に更新を試みる可能性があるため、競合状態が発生しやすくなります。

NoSQL データベースで次のような関係を追跡するにはどうすればよいですか?

  • ユーザーのすべてのコメント
  • すべてのアクティブなコメント
  • [キーワード] でタグ付けされたすべての投稿
  • クラブ内のすべての学生 - または学生が所属しているすべてのクラブ

それとも、これについて間違って考えていますか?

4

5 に答える 5

204

多対多の関連付けを「NoSQL の方法」で保存する方法に対するすべての答えは、データを冗長に保存するという同じことになります。

NoSQL では、データ エンティティ間の関係に基づいてデータベースを設計しません。データベースに対して実行するクエリに基づいて、データベースを設計します。リレーショナル データベースの非正規化に使用するのと同じ基準を使用します。データがまとまりを持つことがより重要な場合 (正規化されたテーブルではなくコンマ区切りのリストの値を考えてください)、そのようにします。

しかし、これは必然的に 1 つのタイプのクエリ (特定の記事に対する任意のユーザーによるコメントなど) を最適化し、他のタイプのクエリ (特定のユーザーによる任意の記事に対するコメント) を犠牲にします。アプリケーションで両方のタイプのクエリを同等に最適化する必要がある場合は、非正規化しないでください。同様に、リレーショナルな方法でデータを使用する必要がある場合は、NoSQL ソリューションを使用しないでください。

非正規化と冗長性には、冗長なデータ セットが互いに同期しなくなるというリスクがあります。これを異常と呼びます。正規化されたリレーショナル データベースを使用すると、RDBMS によって異常を防ぐことができます。非正規化されたデータベースまたは NoSQL では、異常を防ぐためにアプリケーション コードを記述するのはユーザーの責任になります。

NoSQL データベースが異常を防止するという大変な仕事をしてくれたら素晴らしいと思うかもしれません。これを実行できるパラダイム、つまりリレーショナル パラダイムがあります。

于 2010-11-18T00:25:14.740 に答える
4

カウチDBのアプローチでは、マップフェーズで適切なクラスのものを発行し、reduce.で要約することを提案しています。したがって、すべてのコメントをマップ1し、特定のユーザーに対して発行し、後でコメントのみを出力できます。ただし、couchDB で追跡可能なすべてのデータの永続的なビューを構築するには、大量のディスク ストレージが必要です。ところで、関係に関するこの wiki ページもあります: http://wiki.apache.org/couchdb/EntityRelationship

一方、Riak には関係を構築するためのツールがあります。リンクです。「ルート」ドキュメント (ここではユーザー ドキュメント) にリンクされた (ここではコメント) ドキュメントのアドレスを入力できます。それには1つのトリックがあります。配布されている場合、多くの場所で一度に変更される可能性があります。これは競合を引き起こし、その結果、巨大なベクター クロック ツリーが作成されます:/ ..悪くも悪くもありません。

Riak には、さらに別の「メカニズム」もあります。バケットとキーと呼ばれる 2 層のキー名前空間があります。したがって、学生の例では、クラブ A、B、C と学生 StudentX、StudentY がある場合、次の規則を維持できます。

{ Key = {ClubA, StudentX}, Value = true }, 
{ Key = {ClubB, StudentX}, Value = true }, 
{ Key = {ClubA, StudentY}, Value = true }

リレーションを読み取るには、指定されたバケットにキーをリストするだけです。それの何がいけないの?めちゃくちゃ遅いです。バケットの一覧表示は、riak にとって優先事項ではありませんでした。それはますます良くなっています。ところで。{true}この例は StudentX または Y の単一の完全なプロファイルにリンクできるため、メモリを浪費しません(ここでは競合は発生しません)。

ご覧のとおり、NoSQL != NoSQL です。特定の実装を見て、自分でテストする必要があります。

列ストアはリレーションに適しているように見えます..しかし、それはすべて A と C と P のニーズに依存します;) A が必要なく、Peta バイトよりも少ない場合はそのままにしておいてください。MySql または Postgres を使用してください。

幸運を

于 2010-11-15T23:26:09.453 に答える
3
  1. user:userid:comments は合理的なアプローチです。これは、SQL の列インデックスに相当するものであり、インデックスのない列に対してクエリを実行できないという要件が追加されていると考えてください。

  2. ここで、要件について考える必要があります。3000 万個のアイテムを含むリストは、遅いので不合理ではありませんが、それを使って何かをするのは実際的ではないためです。最近のコメントを表示することが実際の要件である場合は、コメントが追加されるたびに更新される非常に短いリストを保持することをお勧めします。NoSQL には正規化の要件がないことを思い出してください。基本的なキー値ストアのリストでは競合状態が問題になりますが、一般的には、プラットフォームがリストを適切にサポートしているか、ロックを使用して何かを実行できるか、失敗した更新を実際に気にしないかのいずれかです。

  3. ユーザー コメントと同じ - インデックス キーワード:posts を作成します。

  4. さらに同じ - おそらく、学生の所有物としてのクラブのリストと、クラブのすべてのメンバーを取得するためのそのフィールドのインデックス

于 2010-11-09T00:51:05.027 に答える
1

あなたが持っている

"user": {
    "userid": "unique value",
    "category": "student",
    "metainfo": "yada yada yada",
    "clubs": ["archery", "kendo"]
}

"comments": {
    "commentid": "unique value",
    "pageid": "unique value",
    "post-time": "ISO Date",
    "userid": "OP id -> THIS IS IMPORTANT"
}

"page": {
    "pageid": "unique value",
    "post-time": "ISO Date",
    "op-id": "user id",
    "tag": ["abc", "zxcv", "qwer"]
}

リレーショナル データベースでは通常、1 対多の関係でデータを正規化します。これは、NoSQL データベースでも行うことと同じです。情報を取得するフィールドにインデックスを付けるだけです。

たとえば、あなたにとって重要な指標は

  • Comment.UserID
  • コメント.ページID
  • Comment.PostTime
  • Page.Tag[]

NosDB (SQL をサポートする .NET ベースの NoSQL データベース) を使用している場合、クエリは次のようになります。

 SELECT * FROM Comments WHERE userid = ‘That user’;

 SELECT * FROM Comments WHERE pageid = ‘That user’;

 SELECT * FROM Comments WHERE post-time > DateTime('2016, 1, 1');

 SELECT * FROM Page WHERE tag = 'kendo'

サポートされているすべてのクエリ タイプを、SQL チート シートまたはドキュメントから確認してください。

于 2016-07-14T06:38:16.183 に答える