提高NDB查询性能

时间:2013-02-13 19:48:19

标签: python google-app-engine optimization app-engine-ndb

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

我的数据模型:

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” - 还有其他方法可以让它更快,因为我仍然不满意性能。

在重复属性中,最多可以有几百个字符串。 事件模型中有几万行。 在eventslist中我只想要几十个偶数。

2 个答案:

答案 0 :(得分:5)

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

你在appstats看过这个吗?你看到get_multi()后没有执行RPC的空格有很大差距吗?这就是反序列化开销。

我发现克服这一点的唯一方法是删除长列表并在单独的模型中管理它们(即,完全避免长时间重复的属性列表),但当然,这可能不适合您的使用情况下。

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

答案 1 :(得分: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(事件列表)*便宜6倍。