【入門編】初心者向け:WP_Queryの「update_post_meta_cache」を制御して不要なSQLを削る – WordPress 内部コア・データベース構造とパフォーマンス最適化解析バイブル

こんにちは!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` の引数に渡すことで、「メタデータの自動キャッシュ生成をするか・しないか」を完全にコントロールできます。

実際のコードを見てみましょう。

  • メタデータのキャッシュ生成をオフにした 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開発の基礎力はもうバッチリマスターできていますよ!ぜひ次の案件や個人開発で試してみてくださいね。それでは、また次の知見でお会いしましょう!

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