我正在运行一个keys_only查询,它会获取20个结果。
result_keys, cursor, more = ActivityIndex.query(cls.followers == key)\
.order(-cls.date_created)\
.fetch_page(num_results,
start_cursor = cursor,
keys_only=True)
然后我获取activityIndex对象的父级:
keys = []
for k in result_keys:
for pair in k.parent().pairs():
keys.append(ndb.Key(pairs=[pair]))
activities_related = ndb.get_multi(keys)
我认为这很快,因为我按键获得了一批对象。但是,查询似乎调用datastore_v3.Next
,根据appstats docs,它是“坏”,并占用了执行时间的很大一部分。
避免不必要的下次通话可能会加快您的应用程序!
以上查询的Appstats(使用get_multi调用)
Appstats用于上述查询,但没有调用get_multi(next()响应的时间很短)。
为什么调用datastore_v3.next()
时get_multi()
调用执行时间过长?它取决于get_multi将返回的结果数量吗? get_multi中返回的一些对象具有列表属性(列表中最多10个项目),这会在性能中起作用吗?
要避免此问题,更改设计并获取tasklet中所需的实体会更好吗?还有其他建议吗?
修改
关于我要做的事情的更多信息:
我的应用程序中有一个活动流,它显示所有用户活动,例如Rob评论了图片等。
为了显示这些信息,我想我需要User对象和Picture Object来构建要显示的活动描述和信息。我将所有这些对象的键设置为ActivityIndex
的父项。因此,从上面的查询中,ndb.get_mult(keys)
将获取Activity,User和Picture对象。 密钥列表可能包含50个或更多密钥,因此这可能是长datastore_v3.Next
次呼叫的原因。
答案 0 :(得分:2)
你是否在dev_appserver中这样做? (我希望不会,因为它的表现与生产环境的表现完全无关,而且我们都在浪费时间讨论这个问题。)
看起来有些东西可疑。 ISTR表示Next调用是异步调度的,在某些情况下实际上并不需要。这可以解释即使你没有重叠调用,第一个图表显示Next重叠了memcache get call。
但是,不应该有那么多延迟。在调用get_multi()之前,你是否正在做你没有显示的额外内容?
顺便说一下你对这些对做的事情看起来过于复杂。如果有任何父母有多对,这将产生无效的密钥。我认为只有一个级别的父母而你只想得到那些 - 如果是这样的话,那就足够了:
keys = [k.parent() for k in result_keys]
最后,请参阅问题118:http://code.google.com/p/appengine-ndb-experiment/issues/detail?id=118 - 我们测量了您似乎正在尝试的技巧,如果您的命中率非常高,那么它是值得的。