2012-04-13 35 views
1

我有一個查詢數據存儲的AppEngine cron作業,然後需要對查詢返回的每個實體做一些工作。預計查詢返回的實體數量有時會很大(> 1000)。查詢結果數量多時使用qry.map_async()是否安全?

我的目標是最大限度地提高併發性並保持較低的內存使用率 - 因爲預期的結果數很大,所以它們可能不適合內存。

由於大#的結果,我應該在它們之間迭代這樣的:

qry = Model.query() 
qit = qry.iter() 
while (yield qit.has_next_async()): 
    entity = qit.next() 
    # Do something with entity 

...或者是可以安全使用更快的map_async()對任意大的結果集進行操作?

@ndb.tasklet 
def callback(entity): 
    # Do something with entity 

qry = Model.query() 
yield qry.map_async(callback) 

我讀過所有的文檔,甚至看了看執行的膽量,它不是完全清楚這些操作的侷限性是大的結果集。

+1

使用「yield something_async()」與使用同步API沒有任何改進,除非您的代碼在tasklet中運行(在這種情況下,它仍然不會運行得更快,但其他的東西可以運行在相同的時間)。 – 2012-04-18 00:24:08

+0

另外,「> 1000」涵蓋了很多。它是> 10,000? > 100,000? > 1,000,000?在某個時候,最好的方法會改變。 – 2012-04-18 00:24:47

+0

嗨,尼克,是的,我的代碼運行在一個tasklet中,我意識到它並不是真的「更快」,而是允許其他tasklet同時運行。感謝澄清。 至於實體數量,我預計這個數字可能會高達10,000。 – 2012-04-18 21:21:13

回答

5

該映射一次讀取一批,然後調用批處理中每個實體的回調。所以這應該沒問題。您也可以嘗試批量大小。

區別在於回調本身會執行更多IO。然後,for循環版本可能會等待每個項目完全處理,而地圖只是開始所有回調,並且只在最後等待它們。所以,更多的並行性,機器人也可能使用更多的內存。

+0

我已經使用tasklet中的map_async實現實現了此cron作業。我正在映射的查詢通常具有1000個或更多結果。大約300次回調成功完成後,出現查詢過期錯誤:「請求的查詢已過期,請使用最後一個遊標重新啓動以讀取更多結果。」我應該做什麼的建議?也許切換到遊標?我應該提到,每個回調都會針對每個外部查詢結果對不同實體(通常在1到3個實體之間)執行map_async操作。 – 2012-08-02 00:32:05

+0

我期望在例如「頁面」中打斷查詢。通過遊標鏈接的100個實體將解決此問題。錯誤消息來自活動查詢的生命週期(我認爲是30秒)和您的cron作業(真正的任務隊列請求)的時間(10分鐘)之間的差異。而且,正如你所說,你爲每個回調做了大量的工作,你需要很長時間處理整個查詢。 map()引入的併發性無論如何都只限於批處理大小,並且如果你有太多未完成的RPC,則無論如何你都會受到限制。 – 2012-08-03 17:15:13

相關問題