我有一個Django模型,其表中有數百萬條記錄。我正在嘗試對外殼中的表中的所有記錄執行一些緊急維護,但是我無法在不完全耗盡系統內存的情況下執行MyModel.objects.all()
。如何迭代Django中的大型表而不會耗盡內存?
即使pass
導致OOM殺手被稱爲,殺死我的過程:
for ii in MyModel.objects.all():
pass
的原因是因爲Django的QuerySet
正試圖建立自己的「結果緩存」,以建立一個列表與所有我在它的記錄,這裏:
# django/db/models/query.py
def _fetch_all(self):
if self._result_cache is None:
self._result_cache = list(self.iterator()) # <<<< this guy!
if self._prefetch_related_lookups and not self._prefetch_done:
self._prefetch_related_objects()
但是我的機器不能保留在內存中的整個列表。
當然,在如此大的表格上迭代.all()
在真實應用程序中會是一個糟糕的主意,所以這個問題的範圍相當有限(維護活動),但它確實時常出現。
嗯,這確實出現了繞過結果緩存,但我仍然(在'Django的/ DB /後端/ utils.py'在'CursorWrapper.execute')運行內存.. 。所以我猜結果緩存不是唯一讓我難過的東西,它只是從postgres獲取的大量記錄... – mgalgs
令我感到驚訝,但我還沒有深入到Django使用的細節遊標與將記錄拉入內存的位置。如果您可以在沒有實際模型實例的情況下進行維護,或者願意將原始數據庫記錄轉換爲模型,那麼從這個答案中鏈接的博客帖子可能會有幫助嗎? HTTP://計算器。com/questions/18381695/get-database-cursor-from-djangos-rawqueryset https://docs.djangoproject.com/en/1.10/topics/db/sql/#connections-and-cursors爲Django文檔。 –
我在模型實例上調用方法,但我完全可以將這些工作分解出來,這是我希望避免的一些工作。這裏和那裏的奇怪維護並不是什麼大不了的事情。我只是希望有一個很好的方法可以做到這一點,而不必下降到原始數據庫記錄。好吧。 – mgalgs