13

問題の例:

エンティティ:

  • ユーザーには名前と友達のリストが含まれています(ユーザーリファレンス)
  • ブログ投稿には、タイトル、コンテンツ、日付、ライター(ユーザー)が含まれています

要件:

ユーザーの友達による過去10件の投稿のタイトルとブログへのリンクを表示するページが必要です。また、古いエントリをページングし続ける機能も必要です。

SQLソリューション:

したがって、SQLランドでは、次のようになります。

select * from blog_post where user_id in(select friend_id from user_friend where user_id =:userId)日付で並べ替え

私が考えることができるGAEソリューションは次のとおりです。

  • ユーザーをロードし、友達のリストをループして、最新のブログ投稿をロードします。最後に、すべてのブログ投稿をマージして、最新の10個のブログエントリを見つけます
  • ブログの投稿には、ライターを友達にしたすべてのユーザーのリストがあります。これは単純な読み取りを意味しますが、ブログ投稿がたくさんある友達を追加すると、クォータが過負荷になります。

これらのソリューションのどちらも拡張できるとは思いません。

他の人がこの問題にぶつかったと確信していますが、私は検索し、google ioビデオを見て、他の人のコードを読みました...私は何が欠けていますか?

4

4 に答える 4

13

提供した SQL ソリューションがどのように実行されるかを見ると、基本的に次のようになります。

  1. 現在のユーザーの友達リストを取得する
  2. リスト内のユーザーごとに、最近の投稿のインデックス スキャンを開始します
  3. ステップ 2 のすべてのスキャンをマージ結合し、十分なエントリを取得したら停止します

Query インスタンスを反復子として使用し、それらに対してマージ結合を行うことにより、App Engine でまったく同じ手順を自分で実行できます。

おっしゃる通り、これは多数の友人にはうまく拡張できませんが、SQL 実装とまったく同じ問題に悩まされています。それは、それらを隠蔽することもできません: 最新の 20 個の (たとえば) エントリをフェッチすると、おおよそのコストがかかりますO(n log n) 個の作業。ここで、n は友達の数です。

于 2009-01-15T11:58:10.587 に答える
7

このトピックは、Google io トークで取り上げられています: http://code.google.com/events/io/sessions/BuildingScalableComplexApps.html

基本的に、Google チームは、リスト プロパティとリレーショナル インデックス エンティティと呼ばれるものを使用することを提案しています。アプリケーションの例は、http: //pubsub-test.appspot.com/にあります。

于 2009-06-25T11:06:54.863 に答える
1

「ユーザーを読み込み、友達のリストをループして、最新のブログ投稿を読み込みます。」

結合とは、ネストされたループです。一部の種類の結合は、ルックアップを伴うループです。ほとんどのルックアップは単なるループです。一部はハッシュです。

「最後に、すべてのブログ投稿をマージして、最新の 10 個のブログ エントリを見つけます」

それはLIMIT付きのORDER BYです。それが、データベースがあなたのために行っていることです。

これについて何がスケーラブルでないのかわかりません。とにかく、それはデータベースが行うことです。

于 2009-01-15T11:59:10.710 に答える
0

http://pubsub-test.appspot.com/から光った python の例を次に示します。

誰でもJava用のものを持っていますか?ありがとう。

from google.appengine.ext import webapp

from google.appengine.ext import db

class Message(db.Model):
 body = db.TextProperty(required=True)
 sender = db.StringProperty(required=True)
 receiver_id = db.ListProperty(int)

class SlimMessage(db.Model):
 body = db.TextProperty(required=True)
 sender = db.StringProperty(required=True)

class MessageIndex(db.Model):  
 receiver_id = db.ListProperty(int)

class MainHandler(webapp.RequestHandler):

 def get(self):
  receiver_id = int(self.request.get('receiver_id', '1'))
  key_only = self.request.get('key_only').lower() == 'on'
  if receiver_id:
    if key_only:
      keys = db.GqlQuery(
          'SELECT __key__ FROM MessageIndex WHERE receiver_id = :1',
          receiver_id).fetch(10)
      messages.extend(db.get([k.parent() for k in keys]))
    else:
      messages.extend(Message.gql('WHERE receiver_id = :1',
                      receiver_id).fetch(10))
于 2009-11-23T22:54:57.357 に答える