web-dev-qa-db-ja.com

ビューのキャッシュ戦略-クエリキャッシュとレンダリングされた出力キャッシュの関係

まず、私はデューデリジェンスを確保し、以前に出てきた質問と重複しないようにしています。 stackexchangeやその他のさまざまな場所で、ビューのキャッシュや、ビューキャッシュのさまざまなタイプに関する特定の詳細(例: here および here )について説明している投稿が多数あります。ただし、ビューキャッシュの異なるレイヤー間の関係と、それらがケース固有のキャッシュの決定にどのように影響するかを十分に説明する詳細はまだわかりません。簡単にするために、私はこの質問の範囲を、コントリビュートスペースで提供される他のレイヤーとは関係なく、すぐに使える7.x-3.xのキャッシュオプションに焦点を合わせています。

ビューは、ディスプレイごとに「クエリ結果」キャッシュと「レンダリングされた出力」キャッシュの2つのレイヤーの時間ベースのキャッシュを公開します。各キャッシュに含まれる生データの詳細は明確ですが、それらの相互作用方法は明確ではありません。レンダリングされたキャッシュへのヒットがクエリキャッシュを完全にバイパスするのか、2つのレイヤーが別々に動作するのか、私は特に疑問に思っています。前者を主張するリファレンス( this one など)と後者を主張するリファレンス( this one など)をいくつか見ました。

理論1-個別のキャッシュレイヤー

私は最初、各レイヤーが「連続して」個別に呼び出され、レンダリングされた出力キャッシュが実際のクエリresultsをハッシュするという印象(および期待)を抱いていましたそのCIDS内。この方法では、新しいコンテンツがビューにすぐに反映されるようにしながら、最も負荷の高いクエリ後のロード/ビルド作業をキャッシュするエレガントな方法があります( "クエリ結果"キャッシュoffおよび「レンダリングされた出力」キャッシュon)。いくつかの簡単なテストでは、レンダリングされた出力キャッシュが現在のクエリ結果を認識していない可能性があるため、これが不可能である可能性があることを明らかにしています。

理論2-レンダリングされた出力キャッシュがクエリ結果キャッシュを「包括」する

もう1つの可能性は、レンダリングされた結果のキャッシュがクエリ自体(結果ではない)のハッシュによってキー設定されることです。この場合、ヒットすると、クエリキャッシュやDBを参照する必要なく、レンダリングされた出力を直接返すことができます。これが事実である場合、「レンダリングされた結果」キャッシュよりも短い時間間隔で「クエリ結果」キャッシュを設定することはあまり意味がないと思います。もちろん、利点は、DBへの直接クエリを回避しながら、レンダリングされた出力をより頻繁に更新できることです(多くの動的テーマロジックまたは頻繁なエンティティの更新がある場合)。ただし、最も複雑なビュークエリを除いて、この種の分離はそれほど有利なようには見えません。

理論2を指す「ブラックボックス」テストをいくつか実行しましたが、他にいくつかの設定が機能しているかどうか、またはビューのバージョンによって答えが異なるかどうかはわかりません。私もコードを少し調べましたが、ほとんどのビューのプラグインメソッドがドキュメント化されておらず、たまに追跡するのが難しいことがイライラしています。とにかく、これに対する答えは、他の人の参考資料として役立つと思います。

7
rjacobs

私はいくつかの内部ビューロジックを調べました。可能な限り、各理論から正しい要素がありますが、どちらも100%正確ではありません。両方のキャッシングレイヤーは独立しており、常に連続してチェックされるため、「レンダリングされた出力」キャッシュにはクエリレイヤーを「バイパス」する機能がありません。さらに、クエリ結果はキャッシュキーにしない因数分解を行うため、クエリ結果への変更は、残念ながらレンダリングされた出力の更新をトリガーしません。


7.x-3.x

「クエリ結果」キャッシュはview::execute()で管理され、「レンダリングされた出力」キャッシュはview::render()で管理されます。 「レンダリングされた出力」キャッシュロジックの前にexecute()が呼び出されるため、「レンダリングされた出力」キャッシュヒットはクエリレイヤーをバイパスできません。表示がキャッシュから完全に構築されるだけの場合、これがクエリの実行やクエリキャッシュのチェックに少しもったいない理由は、私には完全に明らかではありません。 view::execute()には他にもたくさんのロジック(アクセスチェック、フック、プラグイン管理)があり、それらは常にキャッシングとは独立して実行する必要があり、「クエリ結果」のキャッシュパーツをそこから簡単に分離できないと思います。とにかく、その詳細は質問に少し触れていますが、おそらく他の誰かがコメントすることができます。

キャッシュキーの観点から、両方のキャッシュレイヤーは、ビュー名、表示名、キャッシュタイプ、そしてviews_plugin_cache::get_cache_key()からの一連のコンテキスト「スタッフ」のハッシュによってキー付けされます。このget_cache_key()メソッドを見ると、いくつかの一般的なコンテキストデータ(ユーザーロール、言語、base_url)が常に考慮されていることがわかりますが、「レンダリングされた出力」の場合は、生のクエリ文字列もハッシュしますが、クエリ結果はハッシュしません。したがって、生のクエリが変更されると、レンダリングされた出力は更新されますが、クエリ結果が変更された場合でも、レンダリングされた出力はキャッシュから返されます。

したがって、パフォーマンスの観点から、各キャッシュレイヤーは実際には個別に処理できると思いますが、「レンダリングされた出力」キャッシュは、「古くなった」データが表示される頻度を最も直接的に管理します。私はさらにそれを結論付けることができました:

  • ビューのベースアイテムのリストの更新間隔は、いずれかのキャッシュ間隔が大きいか大きいか等しい(実際のアイテムのリストは、両方のキャッシュが期限切れになるまで更新できません)特定のビュー)。
  • 特定のビューの「レンダリングされた出力」キャッシュが「クエリ結果」キャッシュの前に更新される場合、アイテムのリストは更新されませんが、各アイテムに表示されるコンテンツは更新できます(つまり、5秒前にリストに追加された新しいアイテムがまだ)表示されませんが、以前にリストにあったアイテムの5秒前に更新されたティーザーテキストは更新されます)。
  • 「クエリ結果」キャッシュが最終出力に影響を与えていない場合でも、view::execute()のパフォーマンスが向上します。

この動作の一部は、views_plugin_cache::get_cache_key()などのように、views_plugin_cacheクラスのメソッドをローカルで上書きすることで変更できることにも注意してください。

8.0.0

8.0.0-beta7以降、ビュー(コア)は時間ベースのキャッシュのオプションを保持しています。できれば7.x-3.xのように動作することを確認できますが、決定的なテストを行うにはまだ早すぎます。これを参照してください メタディスカッション 。ただし、D8ビューもタグベースのキャッシュをサポートするように見えるため、ビューの時間ベースのキャッシュに関する懸念事項や制限の多くが問題になる可能性があることは明らかです。これは、キャッシュされたデータを本当にスマートに期限切れにする方法を提供するはずです。

4
rjacobs