2013-02-13 168 views
3

我寻求建议,我怎么能在速度方面的改善这一点:提高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” - 有没有其他办法可以使速度更快,因为我仍然不满意性能。

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

+0

我不确定这是否会使性能更好或更差,但也许你可以创建一个参与者实体。 Particpants.query(事件列表中的eventid) – 2013-06-01 05:41:12

回答

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) 

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

5

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

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

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

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