Python 如何通过预取ReferenceProperty属性来防止过度RPC调用?
我试图显示一个包含约800个实体的表,但在保持速度方面存在问题。(大约慢15-20秒)我成功地实现了memcache,但是因为我为每个子实体引用了父模型,所以它仍然会导致800个实体中的每个实体都有一个datastore_v3.Get,速度非常慢 然后我实现了Nick Johnson的,但无法解决以下错误:Python 如何通过预取ReferenceProperty属性来防止过度RPC调用?,python,google-app-engine,memcached,jinja2,Python,Google App Engine,Memcached,Jinja2,我试图显示一个包含约800个实体的表,但在保持速度方面存在问题。(大约慢15-20秒)我成功地实现了memcache,但是因为我为每个子实体引用了父模型,所以它仍然会导致800个实体中的每个实体都有一个datastore_v3.Get,速度非常慢 然后我实现了Nick Johnson的,但无法解决以下错误: [... snipped ...] File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppE
[... snipped ...]
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/myurl/mypythoncode.py", line 67, in get
prefetch_refprops(entitylist, ChildModel.parent_program.name)
File "/myurl/mypythoncode.py", line 36, in prefetch_refprops
fields = [(entity, prop) for entity in entities for prop in props]
TypeError: 'NoneType' object is not iterable
型号:
以下是两个相关模型:
class ParentModel(db.Model):
name = db.StringProperty()
# currently 109 of these
class ChildModel(db.Model):
name = db.StringProperty()
parent_program = db.ReferenceProperty(ParentModel)
website = db.StringProperty()
# currently 758 of these
Python代码:
在我的Python代码中,我使用了Nick Johnson的和for技术。(我在下面包括了ReferenceProperty预取,但没有包括memcaching代码。)
Jinja2模板:
我的Jinja2模板引用了“entitylist”中的iterable“entry”,还引用了parent_program.name和parent_program.key().id()
与
以及其他变体,包括“.name”和“.key().id()”。当我使用“.key().id()”时,我得到一个错误:
AttributeError: 'ReferenceProperty' object has no attribute 'key'
我错过了什么或搞砸了什么?我真的很感激任何帮助 杰德,你做得对:) 两项改进:
def prefetch_refprops(entities, *props):
fields = [(entity, prop) for entity in entities for prop in props]
ref_keys_all = [prop.get_value_for_datastore(x) for x, prop in fields]
ref_keys = [ref_key for ref_key in ref_keys_all if ref_key is not None]
ref_entities = dict((x.key(), x) for x in db.get(set(ref_keys)))
for (entity, prop), ref_key in zip(fields, ref_keys_all):
if ref_key and ref_entities[ref_key]:
prop.__set__(entity, ref_entities[ref_key])
else:
prop.__set__(entity, None)
return entities
(run: real_time, Get #rpcs, RunQuery #rpcs)
Before: 5044 ms, 132, 101
After: 2214 ms, 53, 11
我们的代码正在执行的另一个重链阶梯操作是每个对象的ref_集上的count(),我们将在不久的将来用缓存对象上的值来替换它。删除第一行
entityref=prefetch\u refprops(entitylist,ChildModel.parent\u program.name)
行entitylist
在第一次通过时设置为“无”,因此预取失败。谢谢,我已经解决了这个问题。但现在我得到了“prefetch\u refprops(companylist,ChildModel.parent\u program.name)”的“AttributeError:'str'对象没有属性'get\u value\u for_datastore'”。这似乎有些奇怪,因为它实际上与Nick在其示例中使用的完全相同。好的,我现在修复了它,将其更改为“prefetch_refprops(companylist,ChildModel.parent_program)”。我不会再犯错误了,但感觉我还是做得不对……谢谢,坎比。我最终采用了一种不同的方法,Guido在这里概述了这种方法:但它确实有效!
entityref = prefetch_refprops(entitylist, ChildModel.parent_program)
AttributeError: 'ReferenceProperty' object has no attribute 'key'
def prefetch_refprops(entities, *props):
fields = [(entity, prop) for entity in entities for prop in props]
ref_keys_all = [prop.get_value_for_datastore(x) for x, prop in fields]
ref_keys = [ref_key for ref_key in ref_keys_all if ref_key is not None]
ref_entities = dict((x.key(), x) for x in db.get(set(ref_keys)))
for (entity, prop), ref_key in zip(fields, ref_keys_all):
if ref_key and ref_entities[ref_key]:
prop.__set__(entity, ref_entities[ref_key])
else:
prop.__set__(entity, None)
return entities
(run: real_time, Get #rpcs, RunQuery #rpcs)
Before: 5044 ms, 132, 101
After: 2214 ms, 53, 11