17

django の低レベルの cache.set() 中に何が起こるかを理解しようとしています 特に、クエリセットのどの部分が memcached に格納されるかについての詳細。

まず、django ドキュメントを正しく解釈していますか?

  • クエリセット (python オブジェクト) は独自のキャッシュを持っている/維持しています
  • データベースへのアクセスは遅延です。queryset.count が 1000 であっても、1 レコードに対して object.get を実行すると、その 1 レコードに対して dbase は 1 回だけアクセスされます。
  • apache prefork MPM を介して django ビューにアクセスするとき、特定のデーモン インスタンス X が「tournres_qset = TournamentResult.objects.all()」のようなものを含む特定のビューを呼び出すたびに、これは毎回、新しいtournres_qset オブジェクトが作成されています。つまり、以前の (tcp/ip) アクセスから tournres_qset python オブジェクトによって内部的にキャッシュされた可能性があるものはすべて、新しいリクエストの tournres_qset によってまったく使用されません。

ビュー内の memcached への保存に関する質問です。ビューの上部に次のようなものを追加するとします。

tournres_qset = cache.get('tournres', None)
if tournres_qset is None:
    tournres_qset = TournamentResult.objects.all()
    cache.set('tournres', tournres_qset, timeout)
# now start accessing tournres_qset
# ...

cache.set() 中に何が保存されますか?

  • クエリセット (python オブジェクト) 全体がシリアル化されて保存されますか?

  • クエリセットはまだレコードを取得するために使用されていないため、特定のレコードのコンテンツが実際に memcache に保存されていないため、これは単なる時間の無駄ですか? (今後のリクエストでは、memcache から queryset オブジェクトが取得されます。memcache は、空のローカル クエリセット キャッシュで常に新しく開始されます。dbase へのアクセスは常に行われます。)

  • 上記が当てはまる場合、ビュー全体でいくつかのレコードにアクセスするためにクエリセットが使用された後、ビューの最後にクエリセットを常に再保存する必要があります。これにより、クエリセットのローカルキャッシュが更新されます。常に memcached に再保存されますか? ただし、これにより、クエリセット オブジェクトが再度シリアル化されることになります。物事をスピードアップするのはこれで終わりです。

  • または、cache.set() は queryset オブジェクトを強制的に反復させ、dbase からすべてのレコードにアクセスさせます。これは memcache にも保存されますか? ビューがクエリ セットのサブセットにしかアクセスしない場合でも、すべてが保存されますか?


あらゆる方向に落とし穴があり、多くのことを誤解していると思います。

これが理にかなっていることを願っており、いくつかの「標準」ガイドラインへの説明またはポインタを高く評価しています。ありがとう。

4

1 に答える 1

27

クエリセットは遅延型です。つまり、評価されるまでデータベースを呼び出しません。それらが評価される 1 つの方法は、シリアル化することです。これはcache.set、舞台裏で行われます。いいえ、これは時間の無駄ではありません。必要に応じて、Tournament モデルのコンテンツ全体がキャッシュされます。おそらくそうではありません。クエリセットをさらにフィルタリングすると、Django はデータベースに戻るだけで、全体が少し無意味になります。実際に必要なモデル インスタンスだけをキャッシュする必要があります。

最初のセットの 3 番目のポイントは、Apache やプリフォークとは何の関係もないという点で、まったく正しくないことに注意してください。ビューは他のものと同じように関数であり、関数内のローカル変数で定義されたものはすべて、その関数が戻るときに範囲外になります。したがって、ビュー内で定義および評価されたクエリセットは、ビューが応答を返すと範囲外になり、次にビューが呼び出されたとき、つまり次のリクエストで新しいクエリセットが作成されます。これは、Django にサービスを提供する方法に関係なく当てはまります。

ただし、これは重要です。クエリセットをグローバル (モジュール レベル) 変数に設定するなどの操作を行うと、リクエスト間で保持されます。Django が提供されるほとんどの方法 (これには間違いなく mod_wsgi が含まれます) は、プロセスをリサイクルする前に多くのリクエストに対してプロセスを維持するため、クエリセットの値はそれらのすべてのリクエストで同じになります。これは一種の掘り出し物のキャッシュとして役立ちますが、プロセスがどれくらい続くかがわからないため、正しく取得するのは難しく、さらに、そのグローバル変数の独自のバージョンを持つ他のプロセスが並行して実行される可能性があります.

コメントの質問に答えるために更新されました

あなたの質問は、クエリセットの仕組みをまだ十分に理解していないことを示しています。それらがいつ評価されるかがすべてです。クエリセットをリスト、反復、またはスライスすると、それが評価され、その時点でデータベース呼び出しが行われます(ここでは、反復中のシリアル化を数えます)。クエリセットの内部キャッシュ。そのため、これらのいずれかをクエリセットに対して既に行っており、それを (外部) キャッシュに設定している場合、別のデータベース ヒットは発生しません。

ただし、クエリセットに対するすべてfilter()の操作は、既に評価されているものであっても、別のデータベース ヒットになります。これは、基礎となる SQL クエリの変更であるためです。Django はデータベースに戻り、独自の内部キャッシュを持つ新しいクエリセットを返します。

于 2011-09-30T20:29:11.797 に答える