【入門編】wp_postsテーブルの親子関係(post_parent)と再帰的クエリの負荷軽減策 – WordPress 内部コア・データベース構造とパフォーマンス最適化解析バイブル

こんにちは。WordPressの深淵へようこそ。

今日は、WordPress開発者が必ず一度は直面する「深淵」、そう、`wp_posts` テーブルの `post_parent` による階層構造と、それに伴うパフォーマンスの悪夢についてお話しします。

多くの初心者が「親投稿IDを指定すればいいだけだよね?」と考えますが、その先には「N+1問題」という名の地獄が待っています。今日は、それをスマートに解決する「階層パス(Materialized Path)」という設計術を伝授しましょう。

—

1. なぜ `post_parent` だけではいけないのか?

WordPressのデフォルトでは、階層構造は `post_parent` カラムに親のIDを格納することで表現されます。

  • 何が起きるのか?
  • ある投稿の「全祖先」を取得したいとき、ループの中でクエリを何度も投げる必要があります(再帰的クエリ)。
  • 階層が深くなればなるほど、データベースへの往復回数が増え、表示速度は目に見えて低下します。

例えば、`A > B > C > D` という階層で `D` の祖先を知るために、ループで親を遡る……これではスケールしませんよね。

—

2. 解決策:階層パス(Materialized Path)という設計

データベースの負荷を劇的に減らす手法として、「全祖先のIDを文字列として一つのカラムに持たせる」という戦略があります。

これを実装するために、独自のカスタムテーブル、あるいは `wp_postmeta` を利用しますが、今回は最もパフォーマンスが良い「カスタムカラム(wp_postsに追加)」を想定します。

階層パスの構造イメージ

`post_id: 4` が `1 > 2 > 3` という階層の下にある場合、`hierarchy_path` カラムには `1/2/3/` という文字列を保存します。

  • 利点: 「特定の親配下の全投稿」を取得する際、`LIKE ‘1/2/%’` という単一のクエリで一発取得できます。再帰処理は不要です。

—

3. 実践:同期ロジックの設計

投稿が保存されるたびに、この `hierarchy_path` を自動更新するフックを仕込みます。

/

  • 投稿保存時に階層パスを自動生成する

/
function update_post_hierarchy_path($post_ID, $post, $update) {
// 自身が親を持たない場合はルート
if ($post->post_parent == 0) {
$path = ”;
} else {
// 親のパスを取得し、そこに親のIDを連結
$parent_path = get_post_meta($post->post_parent, ‘_hierarchy_path’, true);
$path = $parent_path . $post->post_parent . ‘/’;
}

// パフォーマンスのためにpostmetaへ保存(本来はwp_postsにカラム追加が理想)
update_post_meta($post_ID, ‘_hierarchy_path’, $path);
}

// 投稿保存のタイミングで実行
add_action(‘save_post’, ‘update_post_hierarchy_path’, 10, 3);

ここがポイント!

  • フックの優先順位: `save_post` は投稿データが確定した直後に走ります。このタイミングでメタデータを更新することで、常に最新のパスを保持できます。
  • 注意点: 投稿が移動(親の変更)された場合、子孫のパスも再帰的に更新する必要があります。これを怠ると整合性が取れなくなるので注意してくださいね。

—

4. 陥りやすい罠:再帰的クエリと「SQLの迷宮」

よくあるエラーとして、`get_posts` 内での再帰的な呼び出しがあります。

// 悪い例:ループの中で何度もデータベースを叩く
foreach ($items as $item) {
$parent = get_post($item->post_parent); // これが毎回クエリを発行する!
}

データベースを叩く回数を減らすのが、WordPress高速化の黄金律です。もし階層パスを使わないのであれば、`get_posts` で一度に全階層のデータを取得し、PHP側で配列として再構築する「メモリ内処理」に切り替えるのが、中級者へのステップアップとなります。

—

まとめ:WordPressを掌握するために

1. 物理構造を知る: `post_parent` は便利だが、大規模データには向かない。
2. 先回りして計算する: 読み込み時に再帰計算せず、書き込み時にパスを計算して保存しておく(これがスケーラビリティの極意です)。
3. クエリを減らす: `LIKE` 検索を使える状態にすることで、データベースの負荷を最小限に抑える。

この階層パスの考え方は、WordPressに限らず、どんなデータベース設計でも使える一生モノの知識です。

「ここをクリアすれば、WordPressの基本はバッチリマスターできますよ」。
次は、このパスを使った「高速なパンくずリスト生成」や「階層別権限チェック」に挑戦してみましょうか。またいつでも聞きに来てくださいね。応援しています。

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