こんにちは!WordPressの裏側の仕組みや、データベースがどうやって動いているのか気になって夜も眠れない…なんて思ったことはありませんか?(笑)
他の言語(Ruby on RailsやLaravelなど)からWordPressに入ってきた開発者の中には、「WordPressって何でもデータベースに放り込んじゃうから、スケールしないんでしょ?」なんて誤解している人が結構多いんです。
でも、それは「データベースのインデックス」という裏側の魔法を知らないだけ。
今回は、カスタム投稿タイプを多用する大規模サイトで絶対に避けて通れない、`wp_posts`テーブルの`post_type`カラムに対するインデックスの重要性を、シニアエンジニアの視点から優しく、そして深く解説していきますね。
ここをクリアすれば、あなたのWordPress開発スキルは一段と洗練されます。一緒にマスターしていきましょう!
—
1. WordPressの心臓部 `wp_posts` テーブルの現実
WordPressのすべての投稿、固定ページ、そして私たちが作るカスタム投稿タイプ(商品、イベント、スタッフ紹介などなど)は、基本的にすべて `wp_posts` という1つの巨大なテーブルに同居しています。
イメージとしては、こんな感じです。
[ wp_posts テーブルのイメージ ]
+—-+———————+——————-+———–+
| ID | post_title | post_content | post_type |
+—-+———————+——————-+———–+
| 1 | Hello world! | Welcome to WP… | post |
| 2 | 会社概要 | ພວກເຮົາは… | page |
| 3 | 極上のコーヒー | 本日は自家焙煎… | product | ← カスタム投稿タイプ
| 4 | 春のセール告知 | 全品20%OFF! | event | ← カスタム投稿タイプ
+—-+———————+——————-+———–+
デフォルトの状態だと、`wp_posts` テーブルにはいくつかのインデックス(索引)が貼られています。主キーである `ID` や、親子関係をたどるための `post_parent` などです。
しかし、ここでひとつの疑問が浮かび上がりますよね。
「あれ? `post_type` にはインデックスってデフォルトで貼られているんだっけ?」
実は、ここがWordPressの歴史と深い関係があるポイントなんです。
—
2. インデックスがない世界:全表スキャン(Full Table Scan)の恐怖
もし `post_type` にインデックス(索引)がなかったら、データベース(MySQL / MariaDB)は裏側でどうやってデータを探すでしょうか?
例えば、あなたがオンラインストアを作っていて、カスタム投稿タイプ `product` の商品一覧をパッと表示させたいとします。
// 商品一覧を取得する典型的なクエリ
$args = array(
‘post_type’ => ‘product’,
‘posts_per_page’ => 10,
);
$products = new WP_Query( $args );
この時、裏側で発行されているSQLクエリはざっくり言うとこんな感じです。
SELECT FROM wp_posts
WHERE post_type = ‘product’
AND post_status = ‘publish’
ORDER BY post_date DESC
LIMIT 10;
もし、`wp_posts` のレコード数が 100万件 に達していたとしましょう。
`post_type` カラムにインデックスがない場合、MySQLはこんな作業を強いられます。
1. 1行目の「Hello world!」を見る。`post_type` は `post` だから違う。
2. 2行目の「会社概要」を見る。`post_type` は `page` だから違う。
3. …(中略:99万9997回チェックする)…
4. 100万行目を見る。`post_type` は `product` だ!これだ!
これがいわゆる「フル表スキャン(Full Table Scan)」です。本棚の本を探すときに、タイトルや索引を見ずに、1ページ目から最後のページまで一文字ずつ探しているような状態ですね。そりゃあCPUも悲鳴を上げますし、ページの読み込みが何秒も遅くなってしまいます。
—
3. インデックスの力:『索引』がある世界
ここで `post_type` カラムにインデックスを追加してみましょう。
— wp_postsテーブルのpost_typeにインデックスを追加するSQL
ALTER TABLE wp_posts ADD INDEX post_type_index (post_type);
(※実は近年のWordPressコアや、多くのモダンな環境ではパフォーマンスチューニングとして考慮される部分ですが、プラグイン等で独自の複合クエリを叩く際にも非常に重要になります)
インデックスが貼られると、データベースの裏側には「どの `post_type` がどの行番号(ID)にあるか」をまとめた「索引リスト(電話帳のようなもの)」が自動で作成されます。
[ post_type の索引イメージ ]
- ‘post’ ===> ID: 1, 5, 8, 12…
- ‘page’ ===> ID: 2, 6, 9…
- ‘product’ ===> ID: 3, 15, 42, 88… (一瞬で見つかる!)
- ‘event’ ===> ID: 4, 11, 20…
これによって、MySQLは100万行をすべて舐めることなく、`’product’` という文字を見た瞬間に該当する行のIDリストへダイレクトにアクセスできるようになります。
これが、クエリ実行計画(EXPLAINの結果)を劇的に改善する正体です。
—
4. 現場でありがちな「陥りやすい文法エラー」とアンチパターン
コードを書くとき、私たちはついつい次のような書き方をしてしまいがちです。ここにデータベースのパフォーマンスを落とす罠が潜んでいます。
❌ やってはいけないクエリの書き方
// 「カスタム投稿タイプを全部まとめて取得したい!」という意図のコード
$args = array(
‘post_type’ => array( ‘product’, ‘event’, ‘news’ ),
// さらにメタデータ(カスタムフィールド)の条件を複雑に絡める
‘meta_query’ => array(
array(
‘key’ => ‘_is_recommend’,
‘value’ => ‘1’,
‘compare’ => ‘=’,
),
),
);
$query = new WP_Query( $args );
一見、何の問題もない綺麗なコードに見えますよね。しかし、`post_type` に適切なインデックスがない状態、あるいは `meta_query`(`wp_postmeta` との結合)が複雑に絡み合うと、MySQLのオプティマイザ(どの子分を使うか決める司令塔)が迷子になり、せっかくのインデックスを使わずにフルスキャンを選んでしまうことがあります。
💡 正しいアプローチと知見
1. 複数の投稿タイプを扱う場合は、インデックスの効き目を意識する
`post_type` に配列を指定した場合、SQLでは `IN (‘product’, ‘event’, ‘news’)` に変換されます。単一の値よりはコストがかかりますが、`post_type` 自体にインデックスがあれば、IN句の検索も非常に高速に処理されます。
2. 不要な `post_type` の混入を避ける
デフォルトの `’post’` や `’page’` を意図せず巻き込んでいないか、クエリの意図を常に明確にしましょう。
—
5. 自分のサイトのクエリを疑え!『EXPLAIN』で実行計画を覗き見する
プロのエンジニアとしてステップアップするために、ぜひ覚えておいてほしい魔法の言葉があります。それが `EXPLAIN` です。
もし、「最近このカスタム投稿一覧ページ、ちょっと重いな…」と感じたら、phpMyAdminやターミナルから、実際のSQLの頭に `EXPLAIN` をつけて実行してみてください。
EXPLAIN SELECT FROM wp_posts WHERE post_type = ‘product’ AND post_status = ‘publish’;
このとき、結果の `key` カラムを見てください。そこが `NULL` になっていたら、それはインデックスが使われておらず、フルスキャンしている証拠です。
逆に、作成したインデックス名(例: `post_type_index` など)が表示されていれば、データベースが綺麗にインデックスを活用して高速にデータを引いてきている証拠になります!
—
まとめ:基礎の積み重ねが、最強のパフォーマンスを生む
今回は、`wp_posts` テーブルの `post_type` カラムとインデックスの関係性について、データベースの裏側の挙動を交えて解説しました。
- WordPressのデータはすべて `wp_posts` に集約されている。
- カスタム投稿タイプが増えるほど、`post_type` による絞り込みの負荷は高まる。
- インデックスを正しく理解・活用することで、数百万件規模のデータでも一瞬でレスポンスを返すことができる。
「動けばいいや」ではなく、「なぜこのクエリは速いのか、なぜこの設計が必要なのか」をロジックで説明できるようになると、あなたのエンジニアとしての市場価値は跳ね上がります。
ここをクリアできれば、もうWordPressのデータベース構造の基礎はバッチリマスターできていますよ!
日々の開発ライフを、より深い知見とともに楽しんでいきましょう。それでは、次の技術トピックでお会いしましょう!