43

これは、querysetiterator()メソッドの django ドキュメントからのものです。

QuerySet は通常、その結果を内部的にキャッシュするため、評価が繰り返されても追加のクエリが発生することはありません。対照的に、 iterator() は、QuerySet レベルでのキャッシュを行わずに結果を直接読み取ります (内部的に、デフォルトの反復子は iterator() を呼び出し、戻り値をキャッシュします)。一度だけアクセスする必要がある多数のオブジェクトを返す QuerySet の場合、これによりパフォーマンスが向上し、メモリが大幅に削減されます。

読んだ後でも、私はまだ混乱しています。パフォーマンスの向上とメモリの削減に関する行は、このiterator()方法を使用する必要があることを示唆しています。誰かが良いケースと悪いケースのiterator()使用例をいくつか挙げることができますか?

クエリ結果がキャッシュされていなくても、本当にモデルに複数回アクセスしたい場合は、誰かが次のことを行うことはできませんか?

saved_queries = list(Model.objects.all().iterator())
4

2 に答える 2

43

あなたが呼び出す文の最初の部分に注意してください。 For a QuerySet which returns a large number of objects that you only need to access once

つまり、これを逆にすると、一連の結果を再利用する必要があり、それらがメモリの問題を引き起こすほど多くない場合は、 を使用しないでくださいiterator。追加のデータベース ラウンド トリップは、キャッシュされた結果を使用する場合と比較して、常にパフォーマンスを低下させるためです。

QuerySet を強制的にリストに評価することはできますが、次のようになります。

  • それはただより多くのタイピングを必要としますsaved_queries = Model.objects.all()
  • Web ページの結果をページ分割しているとします。後続のページネーターが必要な 20 個の結果のスライスを選択できるようにするのではなく、すべての結果を強制的にメモリに格納します (メモリの問題が発生する可能性があります)。
  • QuerySets は lazyであるため、たとえば、すべてのリクエストのコンテキストに QuerySet を配置するコンテキスト プロセッサを使用できますが、特定のリクエストでアクセスしたときにのみ評価されますが、データベース ヒットがリクエストごとに発生する評価を強制した場合

典型的な Web アプリのケースは、比較的小さな結果セットの場合です (タイムリーにブラウザーに配信する必要があるため、必要に応じてページネーションまたは同様の手法を使用してデータ量を減らします)。したがって、一般的には標準的なQuerySet動作が必要です。 . ご存じのとおり、キャッシュの利点を得るには、QuerySet を変数に格納する必要があります。

イテレータの適切な使用: 使用可能なメモリを大量に消費する結果を処理する (小さなオブジェクトが多く、大きなオブジェクトが少ない)。私の経験では、これは重いデータ処理を行うときの管理コマンドでよく見られます。

于 2012-10-02T09:59:42.130 に答える