こんにちは!WordPressの裏側の仕組みやデータベースの挙動に興味を持ってくれて嬉しいです。他の言語(Ruby、Python、PHPのフレームワークなど)を経験したことがある人なら、「なぜWordPressはこんなにたくさんのSQLを勝手に発行するんだろう?」と疑問に思ったことがあるかもしれませんね。
今回は、WordPressのパフォーマンスチューニングの登竜門であり、かつ本質的なアプローチである `WP_Query` の `update_post_meta_cache` パラメータ について、優しく、そして深く解説していきますね。
ここをクリアすれば、あなたも「ただWordPressを使える人」から「WordPressのパフォーマンスをコントロールできるエンジニア」へ一歩踏み出せますよ。一緒にバッチリマスターしていきましょう!
—
1. なぜWordPressは遅くなるのか?(メタデータキャッシュの正体)
まずは、私たちが普段何気なく書いている `new WP_Query()` や `get_posts()` の裏側で、データベース(MySQL)がどう動いているのかを覗いてみましょう。
例えば、次のようなコードを書いたとします。
$query = new WP_Query([
‘post_type’ => ‘post’,
‘posts_per_page’ => 10,
]);
「たった10件の記事を取得するだけだから、軽いだろう」と思いますよね。しかし、デフォルトのWordPressは、これだけの処理を裏で行っています。
1. メインクエリの発行: `wp_posts` テーブルから条件に合う10件の記事IDを取得するSQL。
2. 投稿メタデータの自動一括取得(キャッシュ生成): 取得した10件のすべてのカスタムフィールド(メタデータ)を `wp_postmeta` テーブルから一括で取得するSQL。
イメージ図で表すと、こんな感じです。
[ WP_Query 実行 ]
│
├─ 1. 記事データを取得 (10件)
│ SELECT FROM wp_posts WHERE … LIMIT 10;
│
└─ 2. ★すべてのカスタムフィールドを一括取得★ (メタキャッシュ)
SELECT post_id, meta_key, meta_value
FROM wp_postmeta
WHERE post_id IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
ここにエンジニアとしての「ムダ」が見えますか?
もし、あなたが作りたい画面が「記事のタイトルと日付の一覧リスト」だけで、カスタムフィールドを一切表示しない画面だったとしたらどうでしょう?
ステップ2の「すべてのメタデータを取得する重いSQL」は、100%不要ですよね。にもかかわらず、WordPressの親切心(デフォルト設定)によって、無駄にメモリが消費され、データベースに追加の負荷がかかっているんです。
数万〜数百万レコードを抱える大規模サイトにおいて、この「使わないメタデータの取得」が積もり積もると、データベースのCPU使用率が跳ね上がる原因になります。
—
2. 救世主:`update_post_meta_cache` パラメータの使い方
そこで登場するのが、今回主役である `update_post_meta_cache` です。
このパラメータを `WP_Query` の引数に渡すことで、「メタデータの自動キャッシュ生成をするか・しないか」を完全にコントロールできます。
実際のコードを見てみましょう。
/
$args = [
‘post_type’ => ‘post’,
‘posts_per_page’ => 20,
‘no_found_rows’ => true, // ページネーション用の総件数計算も省くテクニック(ついでに覚えよう!)
‘update_post_meta_cache’ => false, // ★ここでメタキャッシュの自動生成をシャットアウト!
‘update_post_term_cache’ => true, // タロノミー(カテゴリーやタグ)のキャッシュは通常通り生成
];
$custom_query = new WP_Query( $args );
if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) : $custom_query->the_post();
// タイトルとパーマリンクだけを表示する高速なループ
echo ‘
‘ . get_the_title() . ‘
‘;
endwhile;
wp_reset_postdata();
endif;
コードの意味を紐解く
- `’update_post_meta_cache’ => false`:
これが今回の核心です。これを `false` に設定すると、WordPressは `wp_postmeta` テーブルに対する一括取得クエリ(前述のステップ2)の実行をスキップします。結果として、データベースへの問い合わせが1回減り、メモリ消費量も劇的に削減されます。
—
3. 初学者が絶対に陥りやすい「罠」と文法エラー
「じゃあ、すべての `WP_Query` で `false` にしちゃえば最速なんじゃね?」と思ったそこのあなた。ちょっと待ってください!ここにエンジニアがハマりやすい大きな罠があります。
罠:メタデータを取得しようとしてループ内でクエリが爆発する(N+1問題)
もし `update_post_meta_cache => false` に設定したにもかかわらず、テンプレート内で次のようなコードを書いたらどうなるでしょうか?
// ❌ やってはいけないアンチパターン
$custom_query = new WP_Query([
‘post_type’ => ‘post’,
‘posts_per_page’ => 20,
‘update_post_meta_cache’ => false, // キャッシュを切ったのに…
]);
while ( $custom_query->have_posts() ) : $custom_query->the_post();
// ループの中で get_post_meta() を呼んでいる!
$price = get_post_meta( get_the_ID(), ‘price’, true );
echo ‘
価格: ‘ . esc_html( $price ) . ‘
‘;
endwhile;
これをしてしまうと、WordPressは「キャッシュがない!」と気づき、ループの回数分(この場合は20回)、毎回データベースに個別で `get_post_meta` のクエリを発行します。いわゆる「N+1問題」の完成です。1回の大きなクエリよりも、20回の小さなクエリの方がデータベースのコンテキストスイッチが増えて遥かに遅くなります。
正しい判断基準
- メタデータを一切使わない場合(一覧リストなど)
👉 `update_post_meta_cache` を `false` にする(今回覚えたテクニック!)
- メタデータを必ず表示する場合(商品価格やカスタムフィールドの値など)
👉 デフォルト(`true`)のままにしておき、一括でキャッシュさせるのが正解
—
4. まとめ:ここをクリアすればWordPressの基本はバッチリ!
今回は、`WP_Query` の裏側の挙動と、`update_post_meta_cache` を使った不要なSQLの削減方法について解説しました。
- WordPressはデフォルトで「親切心」からすべてのメタデータを一括取得するクエリを投げる。
- カスタムフィールドを使わない一覧画面などでは、`’update_post_meta_cache’ => false` を指定してそのクエリ自体を消し去る。
- ただし、ループ内で `get_post_meta()` を使う場合は `false` にしてはいけない(N+1問題に注意)。
この「データの取得コスト」や「データベースへの影響」を意識できるようになると、書くコードの質がエンジニアの視点にグッと近づきます。
ここをクリアできれば、あなたのWordPress開発の基礎力はもうバッチリマスターできていますよ!ぜひ次の案件や個人開発で試してみてくださいね。それでは、また次の知見でお会いしましょう!