2013-02-03 51 views
4

對於谷歌數據存儲中的100k +實體,ndb.query()。count()將在截止日期前取消,即使使用索引。我試着用produce_cursors選項,但只有iter()或fetch_page()會返回光標,但count()不會。ndb.query.count()在大型實體上的60秒查詢截止日期失敗

如何計算大型實體?

+0

我有同樣的問題,任務隊列中。問題不在於60秒'DeadlineExceededError'對於前端的要求,這對查詢本身的60秒(ISH?)的最後期限,'_ToDatastoreError(ERR)... 超時:數據存儲操作超時,或者數據暫時不可用。「呃,我猜這是OP的問題。 –

回答

2

要做一些昂貴的事情,你應該看看Task Queue Python API。基於任務隊列API,Google App Engine提供了deferred library,我們可以使用它來簡化運行後臺任務的整個過程。

這裏是你如何使用延遲庫在你的應用的例子:

import logging 

def count_large_query(query): 
    total = query.count() 
    logging.info('Total entities: %d' % total) 

然後你可以從調用上述功能的應用程序中,如:

from google.appengine.ext import deferred 

# Somewhere in your request: 
deferred.defer(count_large_query, ndb.query()) 

雖然我仍然不確定count()是否會返回任何帶有如此大數據存儲的結果,但您可以使用此count_large_query()函數,而不是使用遊標(untes TED):

LIMIT = 1024 
def count_large_query(query): 
    cursor = None 
    more = True 
    total = 0 
    while more: 
    ndbs, cursor, more = query.fetch_page(LIMIT, start_cursor=cursor, keys_only=True) 
    total += len(ndbs) 

    logging.info('Total entitites: %d' % total) 

要在本地嘗試上述集LIMIT 4,檢查是否在您的控制檯可以看到Total entitites: ##線。


正如吉在評論中提及這不會擴大規模或者:

這仍然不能擴展(儘管它可能推遲的問題)。任務 有10分鐘而不是1分鐘,所以也許你可以將10x計爲 許多實體。但它非常昂貴!如果你想正確解決這個問題,可以搜索分片 計數器(不幸的是,這是很多工作的 )。

所以你可能想看看best practices for writing scalable applications,尤其是sharding counters

+1

嗯。這仍然沒有規模(儘管它可能推遲了這個問題)。任務有10分鐘而不是1分鐘,所以也許你可以計算10倍的實體。但它非常昂貴!如果你想正確地解決這個問題,可以搜索分片計數器(不幸的是它有很多工作)。 –

+0

@RayYan我我的答案更新圭多的評論後..所以考慮到這一點爲好。 – Lipis

1

最好是使用谷歌應用程序引擎後端。 後端對用戶請求的60秒截止期限和任務的10分鐘截止期限免除,並且無限期地運行。 請看這裏的文件:https://developers.google.com/appengine/docs/java/backends/overview

+0

謝謝,但即使是後端,查詢截止日期60s是不可避免的。 –

+1

這是真的,這是數據庫的API,超時而不是你是從調用它的平臺。這是不可避免的,因爲我從類似的問題/答案中找到了答案。 –

2

這確實是一個令人沮喪的問題。最近我在這方面做了一些工作,以獲得一些統計數據 - 基本上是滿足某些查詢的實體的數量。 count()是一個好主意,但它受到數據存儲RPC超時的困擾。

如果count()以某種方式支持遊標,以便您可以在結果集中進行遊標移動並簡單地將所得到的整數相加而不是返回大量關鍵字僅將它們丟棄,那將會很不錯。使用遊標,您可以在所有1分鐘/ 10分鐘的界限內繼續使用「傳遞接力棒」延遲方法。與count()(而不是fetch(keys_only=True)),你可以大大減少浪費,並希望提高RPC調用的速度,例如,,它需要時間一個令人震驚的量使用fetch(keys_only=True)辦法數到100 - 在後臺一個昂貴的主張。

分片計數器是一個很大的開銷,如果你只需要/想定期計數統計數據(例如,我的系統中的所有賬戶的,例如,國家每日計數)。

+0

這裏的解決方案是使用'db.Query.count',而不是*支持遊標。這是幾分鐘計數和幾秒鐘之間的差異,當計數達數百萬時。使用'deferred.defer'來存儲和轉發結果,在兩個60秒的請求中可以計算出2M。請注意,即使使用'ndb'映射,也可以使用'db.Query.count'。 – technomage