私のチームは GAE (Java) を使用してアプリケーションを作成しており、BigTable のようなオブジェクト指向データベースでのエンティティ関係モデリング (特に多対多) のスケーラビリティに疑問を抱くようになりました。
App Engine データストアで所有されていない 1 対多および多対多の関係をモデル化するための推奨されるソリューション ( JDO のエンティティ関係を参照) は、キーのリストのようです。ただし、Google は次のように警告しています。
「この方法で多対多の関係を実装するには、いくつかの制限があります。最初に、使用できるのは Key オブジェクトだけなので、リストが格納されているコレクションの側で値を明示的に取得する必要があります。もう 1 つのより重要なものは、大きすぎるキーのリストを保存するのは避けたい...」
キーの非常に大きなリストについて言えば、この方法でモデル化を試み、キーごとに 1 つの Long を格納すると仮定すると、エンティティごとの制限が 1MB である場合、エンティティごとの関係の理論上の最大数は ~130k になります。主な利点がスケーラビリティであるプラットフォームの場合、それは実際にはそれほど多くの関係ではありません. そのため、現在、130,000 を超える関係を必要とするシャーディング エンティティを検討しています。
別のアプローチ (リレーションシップ モデル) については、AppEngine 開発者向けリソースのデータストア シリーズのマスターの一部として、Entity Relationships のモデリングに関する記事で概説されています。ただし、ここでも Google はリレーショナル モデルのパフォーマンスについて警告しています。
「ただし、コレクションの接続をたどるとデータストアへの呼び出しが増えるため、十分に注意する必要があります。この種の多対多の関係は、本当に必要な場合にのみ使用し、パフォーマンスに注意して使用してください。あなたの申請。"
ここまでで、「エンティティごとに 130,000 を超えるリレーションシップが必要なのはなぜですか?」と疑問に思っていることでしょう。質問してよかったです。たとえば、100 万人のユーザーを持つ CMS アプリケーションを考えてみましょう (ねえ、私は夢を見ることができますか?!)
ユーザーはコンテンツをアップロードして共有できます: 1. 一般公開 2. 個人 3. グループ 4. 任意の組み合わせ
誰かがログインし、任意のグループでつながっている人からの新しいアップロードを表示するダッシュボードに移動します。このダッシュボードには、公開コンテンツと、このユーザーまたはこのユーザーがメンバーであるグループと明確に共有されているコンテンツを含める必要があります。悪くないですよね?掘り下げてみましょう。
public class Content {
private Long id;
private Long authorId;
private List<Long> sharedWith; //can be individual ids or group ids
}
ID が参照できるすべてのものを取得するためのクエリは、次のようになります。
List<Long> idsThatGiveMeAccess = new ArrayList<Long>();
idsThatGiveMeAccess.add(myId);
idsThatGiveMeAccess.add(publicId); //Let's say that sharing with 0L makes it public
for (Group g : groupsImIn)
idsThatGiveMeAccess.add(g.getId());
List<Long> authorIdsThatIWantToSee = new ArrayList<Long>();
//Add a bunch of authorIds
Query q = new Query("Content")
.addFilter("authorId", Query.FilterOperator.IN, authorIdsThatIWantToSee)
.addFilter("sharedWith", Query.FilterOperator.IN, idsThatGiveMeAccess);
明らかに、私はすでにいくつかのルールを破っています。つまり、2つのINフィルターを使用すると爆発します。私たちが話している限界に近づいている任意のサイズの単一の IN フィルターでさえ、爆発します。それはさておき、結果を制限してページングしたいとしましょう...いいえいいえ! IN フィルターを使用している場合は、これを行うことはできません。この操作を単一のクエリで実行する方法は考えられません。つまり、大量の読み取り時間の処理と複数のカーソルの管理を行わないと、ページネーションを行うことができません。
これを行うために私が考えることができるツールは次のとおりです。非正規化、シャーディング、または関係エンティティです。ただし、これらの概念を使用しても、このデータをスケーリング可能な方法でモデル化する方法がわかりません。明らかにそれは可能です。Google や他の企業は常にそれを行っています。方法がわかりません。これをモデル化する方法を明らかにしたり、NoSQL DB に基づく cms スタイルのアクセス制御のための優れたリソースを紹介したりできますか?