2026年6月22日

2026年6月22日

WordPressの画像はオブジェクトキャッシュで速くなる?Redisが効く範囲と画像キャッシュの正しい設定

結論から言うと、WordPressのオブジェクトキャッシュ(Redisなど)は画像ファイルそのものを保存・配信するしくみではありません。効くのは、画像の情報(添付ファイルの投稿データやメタデータ)を取り出すデータベース処理の部分で、画像ファイルの表示を速くするのはブラウザキャッシュとCDNの役割です。この記事では、その切り分けを整理したうえで、Redisによる永続オブジェクトキャッシュの導入、画像まわりのクエリをキャッシュするコード、画像ファイルのキャッシュヘッダーとCDNの設定、効いているかの確認方法を順に解説します。

画像が表示されるまでの流れと、キャッシュが効く場所

ブログ記事に画像が1枚表示されるまでには、大きく2つの段階があります。

  1. HTMLを作る段階(PHPとデータベース): WordPressが記事を組み立てるとき、画像の <img> タグを出力します。このとき添付ファイルのID、ファイルのパス、幅と高さ、srcset に並べる各サイズのファイル名などを、データベースの wp_posts と wp_postmeta から読み出します。
  2. 画像ファイルを届ける段階(Webサーバー・CDN・ブラウザ): ブラウザはHTMLを受け取ったあと、/wp-content/uploads/ 以下の画像ファイルを別のリクエストで取りに来ます。通常はNginxやApacheが静的ファイルとして直接返し、PHPもWordPressも動きません。

オブジェクトキャッシュが関わるのは1だけです。2の画像ファイルの転送にはまったく関与しないため、「Redisを入れたのに画像の表示が遅いまま」というのは、しくみ上当然の結果です。整理すると次のようになります。

キャッシュの層 何を保存するか 画像に対する効果
オブジェクトキャッシュ(Redis/Memcached) PHPが取り出したデータ(投稿・メタデータ・クエリ結果など) <img> タグを作るためのDB読み出しを減らす
ページキャッシュ 完成したHTML HTML生成全体を省く。画像ファイルは別
ブラウザキャッシュ 画像・CSS・JSファイル 再訪問時に画像の再ダウンロードを省く
CDN 画像などの静的ファイル 利用者に近い拠点から画像を返す

オブジェクトキャッシュが画像まわりで実際にしていること

WordPressには WP_Object_Cache というキャッシュのしくみが組み込まれており、get_post() や get_post_meta() は内部でこれを使います。ただし標準状態では、キャッシュはそのリクエストの処理中だけメモリに置かれ、処理が終わると消えます。同じページ内で同じ画像の情報を何度も読むときは速くなりますが、次の訪問者のリクエストではまたデータベースから読み直します。

RedisやMemcachedを使う永続オブジェクトキャッシュを入れると、このデータがリクエストをまたいで保持されます。画像に関係するものとしては、次のようなデータがキャッシュから返るようになります。

  • 添付ファイルの投稿データ(attachment 投稿タイプの行)
  • 添付ファイルのメタデータ(_wp_attachment_metadata に保存された幅・高さ・各サイズのファイル名など)
  • WP_Query のクエリ結果(WordPress 6.1以降は、条件ごとに取得した投稿IDの一覧がキャッシュされます)

wp_get_attachment_image() や、本文中の画像に srcset と sizes を付ける処理は、このメタデータを参照して動きます。画像が多い一覧ページやギャラリー、商品画像の多いWooCommerceのページほど、データベースへの問い合わせが減る効果が出やすくなります。一方、画像が数枚の記事ページでは差はわずかで、ページキャッシュが効いているページではそもそもPHPが動かないため、オブジェクトキャッシュの出番もありません。

Redisで永続オブジェクトキャッシュを導入する

ここではUbuntu系のサーバーにRedisを入れ、Redis Object Cacheプラグインで接続する例を示します(2026年10月現在)。レンタルサーバーでは、管理画面からRedisやMemcachedを有効化できるプランもあるため、先に提供状況を確認してください。作業前にはサイトのバックアップを取っておきます。

sudo apt update
sudo apt install redis-server php-redis
sudo systemctl enable --now redis-server
redis-cli ping   # PONG が返れば起動している
sudo systemctl restart php8.3-fpm   # PHPのバージョンに合わせて変更

PHPからRedisに接続するための拡張(php-redis)を入れたあと、PHP-FPMを再起動しないと拡張が読み込まれない点に注意してください。次に wp-config.php の「編集が必要なのはここまで」より上に接続設定を書きます。

define( 'WP_REDIS_HOST', '127.0.0.1' );
define( 'WP_REDIS_PORT', 6379 );
define( 'WP_REDIS_DATABASE', 0 );
// 同じRedisを複数サイトで使う場合はサイトごとに変える
define( 'WP_REDIS_PREFIX', 'example_com:' );

プラグインを有効化したら、設定画面またはWP-CLIでドロップイン(wp-content/object-cache.php)を配置します。

wp plugin install redis-cache --activate
wp redis enable
wp redis status

wp redis status で接続済みと表示されれば導入完了です。WordPress 6.1以降のサイトヘルスには、永続オブジェクトキャッシュの利用を勧める項目があり、導入後はこの指摘が消えます。

標準ではキャッシュされない画像の処理を自分でキャッシュする

コア関数の中には、オブジェクトキャッシュを通さずにデータベースへ直接問い合わせるものもあります。代表例が、画像のURLから添付ファイルIDを逆引きする attachment_url_to_postid() です。テーマやプラグインがこれをループ内で呼んでいると、画像の数だけクエリが発生します。

このような処理は wp_cache_get() と wp_cache_set() で包むと、永続オブジェクトキャッシュがある環境ではリクエストをまたいで結果を使い回せます。

<?php
/**
 * 画像URLから添付ファイルIDを取得する(結果を12時間キャッシュ)
 */
function wpdr_cached_attachment_id( $url ) {
	$url = esc_url_raw( $url );
	$key = 'url_' . md5( $url );

	$found = false;
	$id    = wp_cache_get( $key, 'wpdr_attachment', false, $found );
	if ( $found ) {
		return (int) $id;
	}

	$id = attachment_url_to_postid( $url );
	// 見つからなかった場合(0)もキャッシュして、無駄な再検索を防ぐ
	wp_cache_set( $key, $id, 'wpdr_attachment', 12 * HOUR_IN_SECONDS );

	return (int) $id;
}

$found を使っているのは、IDが 0(該当なし)だった場合とキャッシュが存在しない場合を区別するためです。画像を差し替えたり削除したりした直後に古い結果が返るのが困る場合は、delete_attachment などのアクションで該当するキーを wp_cache_delete() してください。

画像ファイルはブラウザキャッシュとCDNで速くする

画像ファイルそのものの表示速度を上げるのは、HTTPのキャッシュヘッダーです。WordPressのメディアライブラリは、画像を差し替えても同じURLを上書きすることが少なく、新しいファイル名で保存されるのが一般的なので、長めの有効期限を設定しやすい種類のファイルです。

Nginxの例です。設定ファイルを変更する前に現在のファイルを複製し、sudo nginx -t で構文を確認してから再読み込みしてください。

location ~* \.(jpe?g|png|gif|webp|avif|svg)$ {
    add_header Cache-Control "public, max-age=2592000";  # 30日
    access_log off;
    try_files $uri =404;
}

ここでつまずきやすいのが、Nginxの add_header の継承です。location の中で add_header を1つでも書くと、server ブロックで設定したセキュリティヘッダーなどの add_header は、その location では送られなくなります。画像にもセキュリティヘッダーを付けたい場合は、同じ location 内に書き直してください。

Apacheでは mod_expires を使います。

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType image/jpeg "access plus 30 days"
  ExpiresByType image/png  "access plus 30 days"
  ExpiresByType image/webp "access plus 30 days"
  ExpiresByType image/avif "access plus 30 days"
</IfModule>

CDNを使う場合は、多くのサービスがオリジンの Cache-Control を尊重するため、上記の設定がそのままCDNのキャッシュ期間の基準になります。同じファイル名で画像を上書きした場合、ブラウザとCDNには古い画像が残るので、CDNのキャッシュ削除(パージ)を行うか、ファイル名を変えてアップロードし直すのが確実です。

効いているかを確認する

導入したキャッシュがどの層で効いているかは、次の方法で確かめます。

  • オブジェクトキャッシュ: Query Monitorプラグインを入れて画像の多いページを開き、データベースクエリの件数とオブジェクトキャッシュのヒット率を見ます。導入前後で、2回目以降の表示のクエリ数が減っていれば効いています。Redis側では redis-cli --scan --pattern '*post_meta*' | head などでキーが作られているかを見られます。
  • 画像のキャッシュヘッダー: curl -I https://example.com/wp-content/uploads/2026/10/sample.webp を実行し、Cache-Control に設定した値が返るかを確認します。CDN経由であれば、Cloudflareの cf-cache-status やCloudFrontの X-Cache などのヘッダーで、CDNのキャッシュから返ったかどうかが分かります。
  • ブラウザ: 開発者ツールのネットワークタブで2回目の読み込み時に、画像が「(disk cache)」や「(memory cache)」から読まれていれば、ブラウザキャッシュが効いています。

まとめ

  • オブジェクトキャッシュは画像ファイルを保存しない。効くのは画像のメタデータや添付ファイル情報、クエリ結果の読み出し
  • 標準のオブジェクトキャッシュはリクエストごとに消えるため、効果を出すにはRedisなどの永続オブジェクトキャッシュが要る
  • attachment_url_to_postid() のようにキャッシュを通らない処理は、wp_cache_get()/wp_cache_set() で包む
  • 画像ファイルの表示速度はCache-ControlヘッダーとCDNで改善する。Nginxの add_header の継承に注意
  • Query Monitor、curl -I、開発者ツールで、どの層が効いているかを分けて確認する

お気軽にご相談ください

お見積りへ お問い合わせへ
▲