2017-04-21 40 views
0

我想要遍歷表(郵政)的所有對象 我使用下面的代碼:獲得從Django的百萬記錄與查詢集是慢

posts = Post.objects.all() 
for post in posts: 
    process_post(post) 

process_post是芹菜的任務,它在後臺運行,並它沒有更新post.But我的問題是郵政表有100萬條記錄。這不是一次性的工作。我每天都在運行它。

for post in posts 

在上面的行中,調用Query可以一次性獲取數據庫中的所有數據。

我該如何提高其性能? 有沒有什麼方法批量提取數據?

+0

是'process_post'的更新方法嗎? – Surajano

+1

使用['iterator()'](https://docs.djangoproject.com/en/dev/ref/models/querysets/#iterator)。如果它仍然導致內存消耗過多,您可能需要考慮使用數據庫端遊標。 –

+1

Data *由Django批量提取。實際上,默認行爲是加載所有內容。但是將行加載爲python對象是一個緩慢的過程,如果你只需要簡單的處理,我建議你儘可能使用'values()'和'update()',甚至是'update()'。 ...並使該處理成爲自定義管理器或查詢集方法。 – spectras

回答

4

製作屬於自己的iterator。例如,說1 million記錄。在查詢集

count = Post.objects.all().count() #1 million 
chunk_size = 1000 
for i in range(0, count, chunk_size): 
    posts = Post.objects.all()[i:i+chunk_size] 
    for post in posts: 
     process_post(post)   

切片將發揮LIMITOFFSET用途。根據chunk_size增加查詢可以減少,因爲內存使用量也增加。針對您的用例進行優化。

2

我的第一個建議是使用select_related或prefetch_related。通過django的文檔並瞭解它,它應該解決你的問題。但是,正如你所說的那樣,你有那張桌子的數百萬條記錄。迭代通過這些將永遠是一個昂貴的業務。如果process_post方法花費時間,最好的解決方案是使用存儲過程。您只需向您的數據庫發出一個請求,而不是循環中的數百萬數據庫調用即可實現目標。