提高NDB查询性能

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” - 是否有其他方法可以使其更快?因为我对性能还不满意。

在重复属性中最多可以有几百个字符串。 活动模型中有几万行数据。 在事件列表中只有几十个事件ID需要获取。


我不确定这样做会使性能变得更好还是更差,但也许你可以创建一个参与者实体。Participants.query(eventid in eventlist) - Rusty Rob
2个回答

5
我发现从协议缓冲区反序列化长列表(即大的repeated=True属性)的开销非常大。
你在appstats中看过这个吗?在get_multi()之后,你是否看到了大量空白的间隙,没有进行RPC操作?这就是反序列化开销。
我唯一发现克服这个问题的方法是删除长列表并将它们管理在单独的模型中(即完全避免长重复属性列表),但当然,这对于您的用例可能不可能。
所以重要的问题是:在获取事件列表时,您真的需要所有参与者吗?还是可以以某种方式推迟查找?例如,同步获取所有事件可能更便宜/更快,然后为每个事件启动异步获取参与者(从不同的模型)并在内存中组合-也许您只需要最近注册的25名参与者或类似的,因此可以限制子查询的成本?

2
简化和执行速度的提高都可能会产生好处,但不一定能降低成本。
data = database.Events.query(database.Events.eventid.IN(eventslist)).fetch(100)

下一步是将事件ID作为键中的ID,并创建如下所示的内容:
event = Event(id=eventid, ...)

如果是这种情况,你就需要这样做。
data = ndb. get_multi(ndb.Key(Event, eventid) for eventid in eventlist)

哪一个更快,而且价格比事件列表的长度乘以6还要便宜。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接