0

私のアプリケーションでは、データストアでFRIENDSリレーションシップテーブルを開発する必要があります。そしてもちろん、私が考えた簡単な解決策は次のとおりです。

user     = db.ReferenceProperty(User, required=True, collection_name='user')
friend   = db.ReferenceProperty(User, required=True, collection_name='friends')

しかし、友達リストが膨大な数、たとえば数千以上に増えるとどうなるでしょうか。これは非効率的すぎますか?

パフォーマンスは常に私たちの優先事項です。これは非常に必要です。これは、この同様の関係設計に従う必要があるためです。

AppEnginePython環境内でデータストアを使用してFRIENDSリレーションシップテーブルを設計するための最良のアプローチについてアドバイスをお願いします。

EDIT FRIENDS関係の他に、FOLLOWER関係も作成されます。そして、私のアプリケーションを対象としたソーシャルメディアがそうなる傾向があるため、ほとんどの場合、これらすべての関係がクエリであることが非常に頻繁にあると思います。

たとえば、一部のユーザーをフォローすると、ユーザーが何をするかなどのニュースフィードとして更新が届きます。また、アクティビティは時間の経過とともに増加します。何人のユーザーかについては、まだ公開されていないため、まだ回答できません。しかし、私は今後数百万人のユーザーがいると予想しています。

うまくいけば、これはより具体的なアドバイスに役立つでしょうか、それともこのアプローチに代わるものがありますか?

4

2 に答える 2

1

FRIENDSモデル(およびおそらくFOLLOWERSモデルも)は適切にスケーリングする必要があります。システムのトリッキーな部分は、実際には、ユーザーのすべての友達やフォロワーからのコンテンツを集約することです。

ユーザーのリストのクエリはO(N)です。ここで、Nは、投稿で説明したテーブルのため、友達の数です。ただし、これらの各クエリでは、友人が共有しているコンテンツを取得するために別のO(N)操作が必要です。これにより、ユーザーが最近のコンテンツを表示するたびにO(N ^ 2)になります。この特定のクエリは、次の2つの理由で不適切です。

  1. O(N ^ 2)操作は、何百万ものユーザー向けのシステムを設計するときにコアアルゴリズムで見たいものではありません。
  2. App Engineは、これらの種類のクエリを制限する傾向があります。具体的には、IN共有アイテムのリストを取得するために使用する必要のあるキーワードは、30人を超える友達には機能しません。

この特定の問題については、各ユーザーを共有コンテンツの各部分にリンクする別のテーブルを作成することをお勧めします。このようなもの:

class SharedItems(db.Model):
  user = db.ReferenceProperty(User, required=True) # logged-in user
  from = db.ReferenceProperty(User, required=True) # who shared it
  item = db.ReferenceProperty(Item, required=True) # the item itself
  posted = db.DateTimeProperty() # when it was shared

更新のストリームをレンダリングするときは、O(N)クエリ(Nは表示するアイテムの数)を使用して、ユーザーと共有されているすべてのアイテムを検索する必要があります(日付の降順)。これをできるだけ速く保つために、Nを小さくしてください。

アイテムを共有するには、O(N)を作成する必要がありますSharedItems。ここで、Nは投稿者の友達とフォロワーの数です。この数が大きすぎて単一のリクエストで処理できない場合は、タスクキューまたはバックエンドにシャーディングしてください。

于 2012-07-14T05:09:53.817 に答える
0

プロパティリストは、GAEで安価でシンプルなインデックスを作成するための優れた方法です。しかし、uが正しく識別したため、いくつかの制限があります。

  1. エンティティ全体のインデックスサイズは制限されています(現在5000だと思います)。したがって、各propertyList値にはインデックスが必要です。したがって、基本的にプロパティリストのサイズは4999未満です

  2. このような大規模なプロパティリストのシリアル化には費用がかかります!! 2Mbエンティティを戻すのは遅いです...そしてCPUのコストがかかります。

大きなpropertyIndexが必要な場合は、実行しないでください。

別の方法は、関係をモデル化するJOINテーブルを作成することです。

 class Friends(db.Model):
  user = db.ReferenceProperty(User, required=True) # logged-in user
  from = db.ReferenceProperty(User, required=True) # who shared it

2つのキーを持つエンティティだけです。これにより、ユーザーのすべての友達を見つけるための簡単なクエリが可能になります。

select from friends where user = : me

私が友達であるすべてのユーザーを見つけます。

select from friends where friend = : me

キーを返すため、uは一括get(keylist)を実行して、実際の友達の詳細を取得できます。

于 2014-03-03T06:22:42.580 に答える