WordPressの深淵へようこそ。コアコントリビューターの視点から、今日は「WordPressのデータベースと階層構造」という、多くのエンジニアが躓き、そして最適化の快感を知る場所についてお話しします。
WordPressのデータベースにおける「親子関係」の基本は、`wp_posts`テーブルの`post_parent`カラムです。これこそが、すべての階層構造の源流。しかし、この「隣接リストモデル」を不用意に再帰的クエリで叩くと、サイトは瞬く間に重くなります。
なぜか? それをどう解決するか。一緒に紐解いていきましょう。
—
1. なぜ「隣接リストモデル」は罠なのか?
`wp_posts`テーブルを見てください。ここには`ID`と`post_parent`というカラムがありますよね。
- ID: 各投稿のユニークな識別子
- post_parent: 親投稿のID(トップ階層なら0)
この構造は「隣接リストモデル」と呼ばれ、非常にシンプルです。しかし、例えば「ある親から派生する全ての孫・ひ孫をフラットに取得したい」と考えた時、素直に再帰的(ループ処理など)にクエリを投げると、階層の深さ分だけデータベースへの負荷(クエリ数)が増加します。
これが「N+1問題」の入り口です。 1つの親を調べて、その子を調べて、さらにその子を……と繰り返していると、パフォーマンスは指数関数的に悪化します。
—
2. インデックス戦略でクエリを高速化する
まず、データベースレベルで最低限やるべきことがあります。それは`post_parent`へのインデックス追加です。
デフォルトのWordPressでは`post_parent`にインデックスが張られていない場合があります。もし大規模なカスタム投稿タイプを運用しているなら、迷わずインデックスを追加してください。
— wp_postsテーブルのpost_parentにインデックスを追加し、検索速度を劇的に向上させる
ALTER TABLE wp_posts ADD INDEX post_parent_idx (post_parent);
これだけで、`WHERE post_parent = 123` というクエリがフルテーブルスキャンを免れ、高速に実行されるようになります。
—
3. 再帰的クエリを回避する「フラット取得」の知見
階層構造をフラットに取得したい場合、最も避けたいのは「階層ごとにWP_Queryを回すこと」です。代わりに、WordPressのキャッシュと内部構造を活かした「一括取得戦略」を使いましょう。
実践的なコード例:一括取得(Eager Loading的アプローチ)
特定の親から、直下の子だけでなく、その先の階層まで一度に取得したい場合、`post_parent__in`という強力な引数を使います。
/
- 特定の親IDから、階層を無視してすべての直下子投稿を取得する関数
/
function get_all_descendant_ids($parent_id) {
global $wpdb;
// 再帰的にクエリを投げるのはNG。まずは直下の子だけを一括取得する
$children = $wpdb->get_col($wpdb->prepare(
“SELECT ID FROM {$wpdb->posts} WHERE post_parent = %d AND post_status = ‘publish'”,
$parent_id
));
return $children;
}
// さらに深い階層が必要な場合、キャッシュを前提にWP_Queryを活用する
$args = array(
‘post_type’ => ‘your_custom_post_type’,
‘post_parent__in’ => array(10, 20, 30), // 親IDを配列で渡せば一括取得可能
‘posts_per_page’ => -1,
);
$query = new WP_Query($args);
—
4. 陥りやすいエラーと解決策
初学者がよくやってしまうミスは以下の2点です。
ミス①:`get_post()` をループ内で何度も呼び出す
これをしてしまうと、キャッシュが効いていない限り、呼び出した回数分だけデータベースへ問い合わせが行きます。
- 解決策: `get_posts()` や `WP_Query` で必要なデータを先に配列として取得し、メモリ上で処理してください。
ミス②:`post_parent` を文字列として判定しようとする
データベースの型は整数(BIGINT)です。`WHERE post_parent = ‘123’` と文字列で比較すると、MySQL側でキャストが発生し、インデックスが使われないことがあります。
- 解決策: 必ず `intval()` を通して整数として渡す癖をつけましょう。
—
先輩からのアドバイス:WordPressを掌握するために
「階層構造を扱う時は、データベースを叩く回数を最小限にする」
これが鉄則です。データベースは一度の問い合わせで「広範囲」を確保し、その後のフィルタリングや並び替えはPHPのメモリ上で行う。このバランス感覚が、世界最高峰のパフォーマンスを生む鍵になります。
最初は複雑に感じるかもしれませんが、`wp_posts`のインデックスを意識し、`WP_Query`の引数を使いこなせるようになれば、WordPressの挙動が手に取るように分かるはずですよ。
ここをクリアすれば、あなたはもうWordPressの基礎を完全にマスターしたも同然です。さあ、次はどんな深い場所へ潜りましょうか?