2013-02-13 111 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個參與者或某個事物因此可以限制您的子查詢的成本?