3

我正在寻求建议,如何在速度方面提高这一点:

我的数据模型:

class Events(ndb.Model):
    eventid = ndb.StringProperty(required=True)
    participants = ndb.StringProperty(repeated=True)

我尝试获取数据的方式:

def GetEventDataNotCached(eventslist):
    futures = []
    for eventid in eventslist:
        if eventid is not None:
            ke = database.Events.query(database.Events.eventid == eventid)
            future = ke.get_async(keys_only = True)
            futures.append(future)

    eventskeys = []
    for future in futures:
        eventkey = future.get_result()  
        eventskeys.append(eventkey)

    data = ndb.get_multi(eventskeys)

因此,我将密钥异步获取,然后将密钥传递给“get_multi”-有没有其他方法可以加快速度,因为我仍然对性能不满意。

在重复属性中,最多可以有几百个字符串。事件模型中有几个 10.000 行。在事件列表中只有几十个我想要获取的 eventid。

4

2 回答 2

5

我发现长列表(即大型repeated=True属性)的协议缓冲区的反序列化开销非常差。

你在 appstats 中看过这个吗?您是否看到在您之后没有执行 RPC 的空白处有很大的空白get_multi()?这就是反序列化开销。

我发现克服这个问题的唯一方法是删除长列表并在单独的模型中管理它们(即,完全避免长重复的属性列表),但当然,这对于您的用例来说可能是不可能的。

所以最大的问题是:当您获得事件列表时,您真的需要所有参与者,还是您可以以某种方式推迟查找?例如,同步获取所有事件可能更便宜/更快,然后为每个事件(来自不同模型)的参与者启动异步获取并在内存中组合 - 也许您只需要 25 个最近注册的参与者或其他东西因此可以限制您的子查询的成本?

于 2013-02-15T17:37:44.953 回答
2

简单性和执行速度方面的改进(而不是成本)可能是:

data = database.Events.query(database.Events.eventid.IN(eventslist)).fetch(100)

下一步是将 eventid 作为键中的 id,创建如下

event = Event(id=eventid, ...)

在这种情况下你做

data = ndb. get_multi(ndb.Key(Event, eventid) for eventid in eventlist)

哪个更快,len(eventlist)*6 便宜。

于 2013-02-14T00:02:23.160 回答