transient とオブジェクトキャッシュの違い|使い分け

結論

  • transient(set_transient): 有効期限つきで保存する仕組み。外部オブジェクトキャッシュが無ければ wp_options テーブルに保存され、リクエストをまたいで残ります。外部オブジェクトキャッシュがあれば、そちらに保存されます。
  • オブジェクトキャッシュ(wp_cache_set): 既定ではメモリ上にだけ置かれ、そのリクエストが終われば消えます。Redis や Memcached などの永続バックエンドを入れたときに、はじめてリクエストをまたいで残ります。

「外部 API の結果を数分〜数時間保持したい」なら transient、「同じリクエスト内で同じ重い処理を2回しない」ならオブジェクトキャッシュ、が基本の使い分けです。

原因・仕組み

公式リファレンスによると、set_transient( $transient, $value, $expiration ) の名前は172文字まで、期限は秒数で、0(既定)は期限なしです。外部オブジェクトキャッシュが有効な場合、transient はデータベースを使わずそのキャッシュに保存されます。また、期限なしの transient は autoload(毎ページ読み込み)の対象になり、期限つきのものは対象になりません。

一方 wp_cache_set( $key, $data, $group, $expire ) は WordPress が内部で使っているキャッシュ API で、投稿やオプションの取得結果もここに入っています。永続化は差し込まれたバックエンド次第です。つまり、テーマやプラグインの作者は、サイトにどちらがあるか分からない前提で書く必要があります。

手順(サンプルコード)

外部 API の結果を1時間 transient に保存する典型例です。

function my_get_rates() {
    $rates = get_transient( 'my_rates' );
    if ( false !== $rates ) {
        return $rates;
    }
    $res = wp_remote_get( 'https://example.com/api/rates' );
    if ( is_wp_error( $res ) || 200 !== wp_remote_retrieve_response_code( $res ) ) {
        return array(); // 失敗は保存しない(または短い期限で保存)
    }
    $rates = json_decode( wp_remote_retrieve_body( $res ), true );
    set_transient( 'my_rates', $rates, HOUR_IN_SECONDS );
    return $rates;
}

同じリクエスト内の重複計算を避けるには、オブジェクトキャッシュを使います。$found を受け取ると、false や空配列を保存した場合も区別できます。

function my_expensive_count() {
    $count = wp_cache_get( 'my_count', 'my_plugin', false, $found );
    if ( $found ) {
        return $count;
    }
    $count = my_heavy_query();
    wp_cache_set( 'my_count', $count, 'my_plugin' );
    return $count;
}

データを更新したときは、delete_transient( 'my_rates' ) や wp_cache_delete( 'my_count', 'my_plugin' ) で古い値を消します。

動作確認(検証環境と結果)

WordPress 7.1.2(ja)/PHP 8.2.12/MariaDB 10.4.32、外部オブジェクトキャッシュなしの環境で、run.php から実行しました(tests フォルダの p2.php)。

same request: 'v'
transient: {"a":1}
options row: true
timeout row: future
autoload: off
miss hit
  • set_transient の値は wp_options に _transient_demo_t として保存され、期限(_transient_timeout_demo_t)は未来の時刻でした。期限つきの autoload は off でした。
  • wp_cache_get の2回呼びは、1回目が miss、2回目が hit でした。
  • レビュー時に、1回目の実行で wp_cache_set( 'rp2k', 'v', 'rp2g' ) し、別プロセスの2回目の実行で wp_cache_get() したところ、値は false、$found も false でした。外部オブジェクトキャッシュが無い環境では、wp_cache の値は次のリクエストに残りません。

transient とオブジェクトキャッシュの違いの注意点

  • transient の期限は「最短でこの時間は残さない」ではなく、期限を過ぎても自動では消えない場合があります(期限切れ行は取得時や掃除処理で削除されます)。期限を過ぎた値は get_transient が false を返すだけだと考えてください。
  • 外部キャッシュの有無で保存先が変わるため、「wp_options に transient がある前提」でデータベースを直接読む実装は避けます。
  • 保存する値が false だと、未保存と区別できません。false を入れたいときは配列に包むか、0 や空文字を使います。
  • 既存の transient を期限指定なし(0)で set_transient() し直すと、値だけが更新され、前回の期限はそのまま残ります(レビュー時の検証: 60秒で保存→期限なしで再保存→_transient_timeout_ は残り約60秒のまま、値は新しいもの)。期限を延ばしたいときは、更新時も期限を渡します。

transient とオブジェクトキャッシュの違いでよくあるミス

  • wp_cache_set を「永続キャッシュ」と思い込み、次のリクエストでも残ると期待する。
  • 利用者ごとに異なる値を共通のキー名で transient に入れる。キーにユーザーIDやパラメータのハッシュを含めます。
  • 失敗した API 応答をそのまま1時間保存してしまい、復旧後も古いエラーが返る。
  • 管理画面で更新した設定が反映されない原因が、削除し忘れた transient だった、というケース。

transient とオブジェクトキャッシュの違いのチェックリスト

  • [ ] リクエストをまたいで残したい値は transient(または option)にしている
  • [ ] 同一リクエスト内の重複処理は wp_cache_* で省いている
  • [ ] キー名に衝突しない接頭辞を付けた(172文字以内)
  • [ ] 更新時に古いキャッシュを削除する処理がある
  • [ ] false を保存する場合の区別方法を決めた

transient とオブジェクトキャッシュの違いのFAQ(よくある質問)

Q. transient と option はどちらがよいですか。
A. 期限が必要で再取得できる値は transient、設定値のように消えては困るものは option です。

Q. 外部オブジェクトキャッシュを入れると、コードは変えるべきですか。
A. 基本的に不要です。同じ API のまま、保存先だけが切り替わります。

Q. マルチサイトでは。
A. サイト全体で共有したい値には set_site_transient を使います。

筆者の見解(transient とオブジェクトキャッシュの違い)

私見では、迷ったときは「消えても再生成できる値か」で判断するのが分かりやすいと考えます。再生成できて、しかも複数リクエストで使い回したいなら transient、リクエスト内だけなら wp_cache_*、消えると困るなら option です。外部キャッシュの有無は環境次第なので、どちらの環境でも動く書き方にしておくのが無難です。

transient とオブジェクトキャッシュの違いの関連項目

出典(一次情報)

タイトルとURLをコピーしました