2

GAE のドキュメントには、次のように記載されています。

各 get() または put() 操作は個別のリモート プロシージャ コール (RPC) を呼び出すため、ループ内でそのような呼び出しを多数発行することは、エンティティまたはキーのコレクションを一度に処理する非効率的な方法です。

コードに他にどれだけの非効率性があるかは誰にもわからないので、できる限り最小限に抑えたいと思います。現在、各反復に個別のクエリがある for ループがあります。私にはユーザーがいて、ユーザーには友達がいるとしましょう。ユーザーのすべての友達の最新情報を入手したい。だから私が持っているのは、そのユーザーの友達の配列です:

for friend_dic in friends:
        email = friend_dic['email']
        lastUpdated = friend_dic['lastUpdated']
        userKey = Key('User', email)
        query = ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated)
        qit = query.iter()
        while (yield qit.has_next_async()):
           status = qit.next()
           status_list.append(status.to_dict())
raise ndb.Return(status_list)

これを行うためのより効率的な方法はありますか、おそらくこれらすべてを 1 つのクエリにバッチ処理することはできますか?

4

2 に答える 2

4

NDB の map 関数を見てみてください: https://developers.google.com/appengine/docs/python/ndb/queryclass#Query_map_async

例 (友人関係を別のモデルに保持すると仮定します。この例では、Relationshipsモデルを想定しています):

@ndb.tasklet
def callback(entity):
  email = friend_dic['email']
  lastUpdated = friend_dic['lastUpdated']
  userKey = Key('User', email)
  query = ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated)
  status_updates = yield query.fetch_async()
  raise ndb.Return(status_updates)

qry = ndb.gql("SELECT * FROM Relationships WHERE friend_to = :1", user.key)
updates = yield qry.map_async(callback)
#updates will now be a list of status updates

アップデート:

データ モデルの理解を深めると、次のようになります。

queries = []
status_list = []
for friend_dic in friends:
  email = friend_dic['email']
  lastUpdated = friend_dic['lastUpdated']
  userKey = Key('User', email)
  queries.append(ndb.gql('SELECT * FROM StatusUpdates WHERE ANCESTOR IS :1 AND modifiedDate > :2', userKey, lastUpdated).fetch_async())

for query in queries:
  statuses = yield query
  status_list.extend([x.to_dict() for x in statuses])

raise ndb.Return(status_list)
于 2012-08-27T20:28:27.820 に答える
1

ndb async メソッドを使用して、これらのクエリを同時に実行できます。

from google.appengine.ext import ndb

class Bar(ndb.Model):
   pass

class Foo(ndb.Model):
   pass

bars = ndb.put_multi([Bar() for i in range(10)])
ndb.put_multi([Foo(parent=bar) for bar in bars])

futures = [Foo.query(ancestor=bar).fetch_async(10) for bar in bars]
for f in futures:
  print(f.get_result())

これにより、10 個のデータストア クエリ RPC が同時に起動され、全体的なレイテンシは、すべてのレイテンシの合計ではなく、最も遅いものにのみ依存します。

API を ndb と非同期にする方法の詳細については、公式のndb ドキュメントも参照してください。

于 2012-08-27T16:39:51.607 に答える