【入門編】wp_postsのpost_contentカラムに格納されるHTMLデータの検索負荷を軽減する手法 – WordPress 内部コア・データベース構造とパフォーマンス最適化解析バイブル

WordPressの「心臓」を軽くせよ:wp_postsの検索負荷を劇的に改善するエンジニアリング術

こんにちは。WordPressのソースコードの深淵を日々覗き込んでいるエンジニアです。

WordPressを使い始めると、誰もが一度はぶつかる壁があります。それは「記事が増えると、サイト内検索やデータ取得が恐ろしく遅くなる」という問題です。

なぜ遅くなるのか? その正体は、`wp_posts` テーブルという巨大な「倉庫」にあります。今日は、この倉庫の構造を紐解き、検索負荷を劇的に減らすための「オフロード戦略」を伝授しましょう。ここを理解できれば、あなたはもう初心者ではありません。

—

1. なぜ `wp_posts` は「ボトルネック」になるのか?

WordPressの `wp_posts` テーブルは、投稿タイトル、本文(`post_content`)、メタデータなどを一手に引き受ける巨大な集積所です。

特に `post_content` カラムは、数万文字のHTMLがテキスト形式で放り込まれています。ここに対して `LIKE` 句を使った検索を投げると、MySQLは以下の地獄のような処理を行います。

  • 全件フルスキャン: インデックスが効かないため、すべてのレコードを一行ずつ読み込む。
  • 重い解析: 巨大なHTML文字列の中からキーワードを探し出す負荷。

これは、図書館の全蔵書を、一冊ずつページをめくって探しているようなものです。これではサイトが重くなるのも当然ですよね。

—

2. 検索負荷を解消する「オフロード」という選択

解決策はシンプルです。「探したいデータだけを、検索に最適化された別の場所へ避難させる」のです。これを「オフロード」と呼びます。

戦略図解:データ分離のイメージ

  • WordPress本体: 記事の管理・保存(書き込み特化)
  • 検索エンジン/専用テーブル: 検索用キーワードの抽出・保持(読み取り特化)

これにより、WordPressは「表示」に専念し、検索エンジンが「検索」を肩代わりする役割分担が生まれます。

—

3. 実践:カスタムテーブルへのデータ抽出

今回は、プラグイン開発の現場でもよく使われる、「投稿保存時に検索用テキストを専用テーブルへ抽出する」手法を紹介します。

ステップ1:専用テーブルの作成

まず、検索用に最適化されたテーブルを用意します。

// プラグイン有効化時に実行
function my_create_search_table() {
global $wpdb;
$table_name = $wpdb->prefix . ‘search_index’;
$charset_collate = $wpdb->get_charset_collate();

// 検索に必要なカラムだけを抽出した軽量なテーブル
$sql = “CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
post_id mediumint(9) NOT NULL,
search_content longtext NOT NULL,
PRIMARY KEY (id),
KEY post_id (post_id) — 高速検索のためのインデックス
) $charset_collate;”;

require_once(ABSPATH . ‘wp-admin/includes/upgrade.php’);
dbDelta($sql);
}

ステップ2:フックを使ってデータを同期

`save_post` フックを使い、記事が保存されるたびにデータを同期します。ここがポイントです。

add_action(‘save_post’, ‘my_update_search_index’, 10, 3);

function my_update_search_index($post_id, $post, $update) {
// リビジョンや自動保存は除外(ここを忘れるとDBが肥大化します!)
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
return;
}

global $wpdb;
$table = $wpdb->prefix . ‘search_index’;

// HTMLタグを除去し、純粋なテキストのみを抽出
$clean_text = strip_tags($post->post_content);

// 既存データがあれば更新、なければ挿入
$wpdb->replace($table, [
‘post_id’ => $post_id,
‘search_content’ => $clean_text
], [‘%d’, ‘%s’]);
}

—

4. 開発者が陥りやすい「罠」

この実装をする際、初学者がよくやってしまうミスを共有しておきます。これに気をつけるだけで、コードの品質は一段階上がります。

1. リビジョン処理の漏れ: WordPressは記事を保存するたびに過去の履歴(リビジョン)を生成します。これを全てインデックスしてしまうと、テーブルがゴミデータで溢れかえります。必ず `wp_is_post_revision` で弾いてください。
2. HTMLタグの混入: `post_content` をそのまま保存すると、`

` といったCSSクラス名まで検索対象になってしまいます。`strip_tags()` で「人間が読むテキスト」だけを抽出するのが鉄則です。
3. 同期の非同期化: 記事数が多い場合、保存のたびにこの処理を走らせると管理画面のレスポンスが悪化します。将来的に大規模なサイトを目指すなら、Action Schedulerなどのライブラリを使って「バックグラウンド処理」に回すのがプロの流儀です。

—

最後に:WordPressを「掌握」するということ

WordPressは、単なる「ブログツール」ではありません。非常に柔軟なデータ構造を持つ、強力なフレームワークです。

`wp_posts` の重さに悩んだとき、「WordPressだから遅くて仕方ない」と諦めるのではなく、「どこを切り離せば高速化できるか?」というエンジニアリングの視点を持ってください。

今回紹介したオフロードの考え方は、Elasticsearchのような外部検索エンジンを導入する際にもそのまま活かせます。一つずつ基礎を積み上げていけば、どんな巨大なサイトでも自在に操れるようになりますよ。

ここをクリアしたあなたは、もうWordPressの「構造」が見え始めているはずです。次なる挑戦を楽しみにしています!

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