2016-08-15 1 views
0

私はテーブルが何百万ものレコードを持っている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() 

しかし、私のマシンはメモリ内のリスト全体を保持することはできません。

このような大きなテーブルでは、実際のアプリケーションでは恐ろしいアイディアになるので、この問題の範囲は限られています(メンテナンス作業)が、時々起こります。

答えて

3

しようとする最初の事はそれを反復する前に、クエリセットにiterator()方法を使用している:

for ii in MyModel.objects.all().iterator(): 
+0

うーん、これは結果キャッシュを回避するように見えるんが、私はまだ( 'ジャンゴ/ DB /バックエンド/ utils.py'でCursorWrapper.execute''で)、メモリが不足しています。..だから私は結果のキャッシュが私を殺す唯一の事ではないと思う、それはポストグルから取り出されたレコードの真の数である... – mgalgs

+0

それは私を驚かせるが、私はDjangoがカーソルとレコードをメモリにプルする場所。実際のモデルインスタンスなしでメンテナンスを行うことができたり、生のデータベースレコードをモデルに変換しようとしている場合、この回答からリンクされたブログ記事の1つが役立つでしょうか? http:// stackoverflow。com/questions/18381695/get-database-cursor-from-djangos-rawqueryset https://docs.djangoproject.com/en/1.10/topics/db/sql/#connections-and-cursors for Djangoドキュメント。 –

+0

私はモデルインスタンス上のメソッドを呼び出していますが、私はそれを完全に取り除くことができます。これは避けたい作業でした。こことそこの奇妙なメンテナンスのための大したことではありません。私は、生のデータベースレコードに落とさずにこれを行う良い方法があることを期待していました。しかたがない。 – mgalgs

0

完全なレコードのすべてをメモリに収めることはできないかもしれませんが、すべての主キーをメモリに収めることができます。ですから、すべてのプライマリキーのリストを反復処理し、それぞれに.get()を行うと、個別のレコードを操作することができます

for pk in MyModel.objects.values_list('pk', flat=True): 
    ii = MyModel.objects.get(pk=pk) 
    ii.maintenance_activity() 

をこれはもちろん、スーパーCPU効率的ではありませんが、それは多くのメモリが効率的です。このようなことがメンテナンス活動のためだけに出てくるべきであることを考えれば、理想的でないパフォーマンスはうまくいけば問題ではないはずです。

0

あなたがpython3.Xを使用している場合は、いくつかの非同期タスクを試すことができます。

スケジュールフェッチを作成すると便利です。

このような何か:

async def _fetch_all(self): 
    if self._result_cache is None: 
      self._result_cache = await list(self.iterator()) # <<<< this guy! 
    if self._prefetch_related_lookups and not self._prefetch_done: 
      await self._prefetch_related_objects() 

あなたのコードを実行するには:

import asyncio 
my_model = MyModel() 
asyncio.get_event_loop().run_until_complete(my_model._fetch_all()) 

しかし、あなたは2.7を使用している場合は、セロリと非同期タスクを作成する必要があるか、それを行うためにいくつかのツールを試してみますDjango Asyncのように。

希望します。

Take a look

関連する問題