Transient APIを使用してHTML文字列またはオブジェクトを保存する必要がありますか?


18

非常に複雑なクエリで20の関連投稿(各投稿)を表示するプラグインがあると仮定しましょう。そして、このクエリのデータを使用して、複雑なHTMLレイアウトを構築します。また、プラグインはパブリックであり、任意の構成の任意のサーバーにインストールできることに注意してください。

何かのようなもの:

/* complex and large query */
$related_posts = get_posts( ... );

$html_output = '';
foreach($related_posts as $key => $item) {
     /* complex layout rendering logic (but not as slow as the previous query) */   
     $html_output .= ...;
}

だから私の質問は:

  • そのようなデータをキャッシュする最も安全で最も正しい方法は何ですか?
  • Transient APIを使用して$related_posts配列または$html_output文字列をキャッシュする必要がありますか?$html_ouput文字列をキャッシュする場合、最大サイズの制限に達しますか?保存する前に、gzipする必要がありますか?
  • ここでTransient APIを使用する必要がありますか?

回答:


18

ここでTransient APIを使用する必要がありますか?

番号。

在庫のWordPressインストールトランジェントはwp_optionsテーブルに保存され、コアアップグレード中にのみクリーンアップされます。50,000件の投稿があるとします。これは、オプションテーブルに50,000行追加されます。明らかにautoload = noに設定されているため、すべてのメモリを消費するわけではありませんが、別の警告があります。

オプションテーブルのautoloadフィールドにはインデックスがありません。つまり、への呼び出しでwp_load_alloptions()全テーブルスキャンが実行されます。行が多いほど、時間がかかります。オプションテーブルに頻繁に書き込むほど、MySQLの内部キャッシュの効率は低下します。

キャッシュされたデータが投稿に直接関連している場合は、投稿メタに保存することをお勧めします。また、これにより、キャッシュされたコンテンツを表示する必要があるたびにクエリが保存されます。これは、WP_Queryでのポスト取得中にポストメタキャッシュが(通常)準備されるためです。

メタ値のデータ構造はさまざまである可​​能性があり、キャッシュされた値が古い場合は、タイムスタンプを取得して高価なクエリを実行できます。

念頭に置いておくべきもう1つの重要な考え方は、WordPressの一時的なオブジェクトは、永続的なオブジェクトキャッシュを使用する環境では不安定になる可能性があるということです。これは、キャッシュされたデータを一時的に24時間保存した場合、23時間、12、5分で利用可能になるという保証はまったくありません。多くのインストールのオブジェクトキャッシュバックエンドは、RedisやMemcachedなどのメモリ内のキーと値のストアであり、新しいオブジェクトに合わせて十分なメモリが割り当てられていない場合、古いアイテムは削除されます。これは、メタストレージアプローチにとって大きな勝利です。

無効化も賢くなります。つまり、関連する投稿キャッシュをX時間で無効にするのはなぜですか?一部のコンテンツが変更されたためですか?新しい投稿が追加されましたか?新しいタグが割り当てられましたか?「複雑で大きなクエリ」に応じて、クエリの結果を変更するようなことが起こった場合にのみ無効にすることを選択できます。

Transient APIを使用して$ related_posts配列または$ html_output文字列をキャッシュする必要がありますか?$ html_ouput文字列をキャッシュすると、最大サイズの制限に達しますか?保存する前に、gzipする必要がありますか?

これは文字列のサイズに大きく依存します。これは、PHP、MySQLなどの間を流れるデータだからです。わずか1 MB

「複雑なレイアウトレンダリングロジック」は実際にどれくらいかかりますか?プロファイラで実行して調べてください。非常に高速であることがボトルネックになることはないでしょう。

その場合は、投稿IDをキャッシュすることをお勧めします。WP_Postオブジェクトではなく、これらには完全な投稿コンテンツが含まれますが、投稿IDの配列のみが含まれます。次に、主キーによる非常に高速なMySQLクエリをもたらすWP_Querya post__inを使用します。

つまり、アイテムごとに必要なデータ、たとえばタイトル、サムネイルURL、パーマリンクが非常に単純な場合、MySQLへの余分なラウンドトリップのオーバーヘッドや、非常に長いHTMLをキャッシュするオーバーヘッドなしで、これら3つだけを保存できます文字列。

うわー、それはたくさんの言葉です、それが役立つことを願っています。


12

すべてのWPコードがパブリックコードではない

あなたが何かを公開するつもりなら、コブシェニンが言ったことはすべて完全に有効です。

あなた自身またはあなたの会社のためにプライベートコードを書くつもりなら、状況は異なります。

外部オブジェクトキャッシュは、どんな場合でも大きなメリットです

可能であれば、外部永続オブジェクトキャッシュを設定することをお勧めします。

過渡現象とMySQLに関するkovsheninの答えで述べられたすべてのことは非常に真実であり、WP自体と多くのプラグインがオブジェクトキャッシュを使用することを考慮すると... RedisやMemcachedのような最新のキャッシュシステム。

キャッシュされた値が存在しない可能性がある:それは問題ありません

さらに、はい、外部オブジェクトキャッシュは信頼できません。トランジェントが存在するという事実に決して頼るべきではありません。キャッシュが本来あるべき場所にない場合、それが機能することを確認する必要があります。

キャッシュはストレージではなく、キャッシュはキャッシュです。

キャッシュを選択的に使用する

この例を参照してください。

function my_get_some_value($key) {
   // by default no cache when debug and if no external object_cache
   $defUse = ! (defined('WP_DEBUG') && WP_DEBUG) && wp_using_ext_object_cache();
   // make the usage of cache filterable
   $useCache = apply_filters('my_use_cache', $defUse);
   // return cached value if any
   if ($useCache && ($cached = get_transient($key))) {
     return $cached;
   }
   // no cached value, make sure your code works with no cache
   $value = my_get_some_value_in_some_expensive_way();
   // set cache, if allowed
   $useCache and set_transient($key, $value, HOUR_IN_SECONDS);

   return $value;
}

このようなコードをプライベートサイトで使用すると、特に多くのユーザーがいる場合、サイトのパフォーマンスが大幅に向上ます。

ご了承ください:

  • デフォルトでは、デバッグがオンの場合、キャッシュは使用されないため、開発環境で使用することをお勧めします。私を信じて、キャッシュはデバッグを地獄にすることができる
  • WPが外部オブジェクトキャッシュを使用するように設定されていない場合、デフォルトではキャッシュも使用されません。これは、MySQLを使用するときにトランジェントを使用しないため、MySQLに関連するすべての問題が存在しないことを意味します。おそらくもっと簡単な代替手段は、wp_cache_*functionsを使用することです。したがって、外部キャッシュが設定されていない場合、キャッシュはメモリ内で発生し、データベースは関与しません。
  • キャッシュの使用はフィルタリング可能で、発生する可能性のあるいくつかのエッジケースを処理します

キャッシュがなければWebscaleはありません

キャッシュの速度の問題を解決しようとしないでください。速度に問題がある場合は、コードを再考する必要があります。

しかし、webscaleでWebサイトをスケーリングするには、キャッシュがかなり必要です

また、多くの場合(常にではありませんが)断片化されたコンテキスト対応キャッシュは、積極的なフルページキャッシュよりもはるかに柔軟で適切です。

あなたの質問:

ここでTransient APIを使用する必要がありますか?

それは依存します。

あなたのコードは多くのリソースを消費していますか?そうでない場合、キャッシュの必要はないかもしれません。前述のように、スピードだけではありません。コードの実行速度は速いが、2人のユーザーに大量のCPUとメモリが必要な場合... 100人または1000人の同時ユーザーがいる場合はどうなりますか?

キャッシュを実現することをお勧めします。

...そして公開コードです:おそらくnoです。上記の公開コードの例のように、選択的にキャッシュすることを検討できますが、そのような決定を実装者に任せた方が通常は優れています。

...そしてプライベートコードです:おそらくyesです。ただし、プライベートコードの場合でも、たとえばデバッグの場合など、選択的にキャッシュすることは良いことです。

とにかく、wp_cache_*関数はデータベースを汚染するリスクなしにキャッシュにアクセスできることを覚えておいてください。

Transient APIを使用して$ related_posts配列または$ html_output文字列をキャッシュする必要がありますか?

それは多くのことに依存します。文字列の大きさは?どの外部キャッシュを使用していますか?投稿をキャッシュする場合は、IDを配列として保存することをお勧めします。IDで適切な数の投稿を照会するのは非常に高速です。

最終ノート

Transient APIは、おそらくWordPressの最高の機能の1つです。あらゆる種類のキャッシュシステムで使用できるプラグインのおかげで、内部で機能する多数のソフトウェアにとって愚かな単純なAPIになります。

WordPress以外では、さまざまなキャッシングシステムを使用してすぐに動作し、1つのシステムから別のシステムに簡単に切り替えることができる抽象化を見つけるのは非常に困難です。

WordPressが他の最新のものより優れていると言っているのを聞くことはめったにありませんが、一時的なAPIはWordPressで作業していないときに見落とす数少ないものの1つです。

確かにキャッシュは難しく、コードの問題を解決せず、特効薬ではありませんが、動作する高トラフィックサイトを構築するために必要なものです。

最適化されていないMySQLテーブルを使用してキャッシュを実行するというWordPressのアイデアは非常に正気ではありませんが、デフォルトでWordPressが実行するからといって、キャッシュから遠ざけるのは良くありません。

あなたは物事がどのように機能するかを理解する必要があり、それからあなたの選択をします。


2

これまでの回答は、必須の「依存する」をすでに強調しており、それに完全に同意します。

ただし、上記のシナリオでこれを行うのが最適であると仮定する」方法に基づいて、推奨事項を追加したいと思います。

その場合はTransientsを使用せず、むしろMetaをポストします。後者の利点の1つは、Controlです。

投稿ごとにデータをキャッシュする必要があるため、キャッシュするデータの量は投稿の数に依存し、時間とともに増加します。特定の数の投稿を超えると、オブジェクトキャッシュが使用できるメモリの制限に達する可能性があり、期限切れになる前に以前にキャッシュされたデータのメモリからの消去が開始されます。これにより、ビジターが大量に流入し、各ビジターがページリクエストごとに「過度に複雑なSQL」をトリガーし、サイトが完全に停止するという状況が発生する可能性があります。

ポストメタにデータをキャッシュすると、データの格納方法と取得方法を制御できるだけでなく、更新方法を正確に制御することもできます。サイトへのトラフィックがほとんどない、またはまったくない時間帯にのみ実行されるcronジョブを追加します。そのため、サイトの実際のユーザーが「スロークエリ」に遭遇することはなく、プリロードすることもできます。これにより、最初の訪問者がヒットしたときに作業が完了します。

すべてのキャッシュはトレードオフであることに注意してください!そのため、通常の答えは「それは依存します」です。そしてなぜ「聖なるキャッシングの聖杯」がないのか。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.