如何在调用get_multi时阻止应用程序调用datastore_v3.next()?

时间:2012-11-02 09:18:10

标签: python google-app-engine google-cloud-datastore app-engine-ndb appstats

我正在运行一个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 view with get_multi enabled

Appstats用于上述查询,但没有调用get_multi(next()响应的时间很短)。 short time for next to respond

为什么调用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次呼叫的原因。

1 个答案:

答案 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 - 我们测量了您似乎正在尝试的技巧,如果您的命中率非常高,那么它是值得的。