【入門編】初心者向け:WP_Queryの「s」パラメータによるキーワード検索が遅い理由と部分一致検索の限界 – WordPress 内部コア・データベース構造とパフォーマンス最適化解析バイブル

こんにちは!WordPressの裏側の仕組みやデータベースとの対話に興味を持ってくれて嬉しいです。他の言語やフレームワークを少し知っている方なら、「あれ、WordPressの検索って、記事が増えると急に重くなるな?」と気づいた瞬間があるかもしれません。

今回は、WordPressの検索機能の心臓部である `WP_Query` の `s` パラメータ(キーワード検索)が、なぜ遅くなってしまうのか、そのデータベース内部の秘密を優しく、かつ徹底的に紐解いていきますよ。

ここをクリアすれば、WordPressのパフォーマンスチューニングの基礎はバッチリマスターできます。一緒にその仕組みを覗いてみましょう!

—

1. なぜ `WP_Query` のキーワード検索は遅くなるのか?

まずは、普段私たちが何気なく書いているコードを見てみましょう。

// キーワード「WordPress」を含む投稿を検索する一般的なクエリ
$args = array(
‘post_type’ => ‘post’,
‘s’ => ‘WordPress’,
);

$query = new WP_Query( $args );

if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
// 投稿の表示処理
the_title();
}
}
wp_reset_postdata();

このコード自体はとてもシンプルですよね。初心者の方でもすぐに書けるお馴染みの書き方です。
しかし、この裏側でデータベース(MySQL)が何をしているかを知ると、少し冷や汗をかくかもしれません。

データベースの裏側で起きていること

WordPressはこのクエリを受け取ると、内部で次のようなSQL文を自動的に組み立てて実行します。(※分かりやすく簡略化しています)

SELECT FROM wp_posts
WHERE post_type = ‘post’
AND (post_title LIKE ‘%WordPress%’
OR post_content LIKE ‘%WordPress%’);

ここで注目してほしいのが、`LIKE ‘%WordPress%’` という部分です。これが、検索が遅くなるすべての元凶なんです。

—

2. 図解:なぜ `LIKE` 検索はインデックスを無効化するのか?

データベースには、データを高速に見つけるための「インデックス(索引)」という仕組みがあります。本の後ろにある「索引ページ」をイメージしてください。本来なら、「WordPress」という単語がどこにあるか、一瞬で引き当てることができます。

しかし、`LIKE` 検索の前後に `%`(ワイルドカード)が付くと、MySQLのインデックスは完全に無力化されてしまいます。

【辞書の索引のイメージ】
通常の検索(前方一致: ‘WordPress%’)
└ 「W」のページを開いて、上から順番に探す(インデックス有効!)

部分一致・前後一致(’%WordPress%’)
└ 「文字の途中に含まれるかもしれない」
└ 索引が使えない!
└ 仕方ないので、全ページの1行目から最終行まで
全部の文字を目視で読み始める(= フルテーブルスキャン)

データベースは、保存されているすべての投稿のタイトルと本文を、1行目から最後の行まですべて舐めるようにチェック(フルテーブルスキャン)します。
記事が100件なら一瞬ですが、10万件に増えたらどうなるでしょう? サーバーは悲鳴を上げ、CPU使用率は跳ね上がり、ページの表示速度はガクッと落ちてしまいます。これが、WordPressのキーワード検索の限界と正体です。

—

3. 初心者が陥りがちな文法・設計エラー

この仕組みを知らないまま、さらに次のような実装をしてしまう初学者の方がよくいらっしゃいます。

❌ やってしまいがちな重いクエリの例

// 複数のキーワードやメタデータ(カスタムフィールド)をLIKEで組み合わせる
$args = array(
‘post_type’ => ‘post’,
‘s’ => ‘カスタム 開発’, // これも内部で複数のLIKEに分解される
‘meta_query’ => array(
array(
‘key’ => ‘location’,
‘value’ => ‘東京’,
‘compare’ => ‘LIKE’, // ここでもLIKEを使っている!
),
),
);
$query = new WP_Query( $args );

「キーワード検索 (`s`)」に加え、カスタムフィールドの「部分一致 (`LIKE`)」まで同時にやってしまうと、MySQLは複数の巨大なテーブルに対してフルテーブルスキャンを強制されます。これはデータベースにとって大変な重労働です。

—

4. どうやって解決する? 検索精度と速度のバランス

「じゃあ、WordPressで高速な検索をするのは無理なの?」と不安になりますよね。安心してください。実務の現場では、次のようなアプローチでこの限界を突破します。

解決策 ①: 検索対象をタイトルや抜粋に絞る(簡易的な負荷軽減)

本文 (`post_content`) は文字数が多く、検索に時間がかかります。タイトル (`post_title`) だけを検索対象にするフィルターを使うことで、スキャンの負荷を大幅に軽減できます。

// キーワード検索の対象をタイトルだけに限定するフック
function my_search_by_title_only( $search, $wp_query ) {
if ( ! empty( $wp_query->get( ‘s’ ) ) && ! is_admin() ) {
global $wpdb;
$keyword = ‘%’ . $wpdb->esc_like( $wp_query->get( ‘s’ ) ) . ‘%’;
// 本文(post_content)の検索条件をごっそり削る
$search = $wpdb->prepare( ” AND ({$wpdb->posts}.post_title LIKE %s) “, $keyword );
}
return $search;
}
add_filter( ‘posts_search’, ‘my_search_by_title_only’, 10, 2 );

※上記はあくまで一例です。運用するサイトの要件に合わせて慎重に適用してくださいね。

解決策 ②: 本格的な全文検索エンジン(Elasticsearch等)や外部サービスの導入

数万件を超える大規模なメディアサイトやECサイト(WooCommerceなど)では、デフォルトのMySQLによる `LIKE` 検索を諦め、Elasticsearch や Algolia といった専用の外部検索エンジンと連携するのがプロの定石です。これらはテキスト専用の高速な索引(転倒インデックス)を持っているため、何百万件の記事があっても一瞬で結果を返してくれます。

—

まとめ

今回は `WP_Query` の `s` パラメータが遅くなる理由と、その裏側にあるデータベースの仕組みを解説しました。

  • `LIKE ‘%キーワード%’` はインデックスを効かせられないため、フルテーブルスキャン(全件走査)が発生する。
  • データ量が増えると、検索処理がサーバーのボトルネックになりやすい。
  • 要件に応じて、検索対象を絞る工夫や、外部の検索エンジンを検討することが重要。

「なぜこのコードを書くと重くなるのか」というデータベース視点での理由が分かると、コードを書くときの意識がガラリと変わりますよね。ここを理解できたあなたは、もうただの初心者ではありません。一歩進んだWordPressエンジニアの仲間入りです!

明日からの開発に、ぜひこの知見を活かしてみてくださいね。それでは、次のステップでも一緒に楽しくマスターしていきましょう!

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