こんにちは。WordPressの深淵へようこそ。
今日は、多くの開発者が「なんとなく」使い続け、そして大規模サイトで必ずと言っていいほど躓く「ページネーションの罠」についてお話しします。
「記事一覧を表示するだけなのに、なぜサイトが重くなるのか?」
その答えは、WordPressのデフォルトが採用している`SQL_CALC_FOUND_ROWS`という呪縛にあります。これを解き放ち、データベースを味方につける術を身につけましょう。
—
1. なぜ「全件カウント」が敵なのか?
WordPressで `WP_Query` を使うとき、私たちは無意識に `$query->found_posts` を使ってページネーションを生成しますよね。
内部的に何が起きているかというと、MySQLに対してこのようなクエリが発行されています。
— 実際はもっと複雑ですが、本質はこれです
SELECT SQL_CALC_FOUND_ROWS FROM wp_posts WHERE post_type = ‘post’ LIMIT 10;
SELECT FOUND_ROWS(); — ここで全件数を取得
ここでの最大のボトルネックは、`SQL_CALC_FOUND_ROWS` がテーブル内の該当する行をすべてスキャンし、インデックスが効かないケースでフルテーブルスキャンを誘発することです。
10万件の記事があるブログで、これを実行するとどうなるか? MySQLは「どれだけ時間がかかってもいいから、とりあえず全件数え上げる」という重労働を強いられます。ページングのために全件をカウントするのは、大規模サイトにおいては「罪」に近い非効率さなのです。
—
2. 「脱・全件カウント」の設計パターン
では、どうすればいいのか? 答えはシンプルです。「全件数を正確に把握することを諦める」、あるいは「カウント専用の超軽量クエリを別途発行する」というアプローチです。
アプローチA:`no_found_rows` を活用する
`WP_Query` の引数に `no_found_rows => true` を渡すと、WordPressは全件カウントをスキップします。
$args = [
‘post_type’ => ‘post’,
‘posts_per_page’ => 10,
‘no_found_rows’ => true, // これをtrueにするとSQL_CALC_FOUND_ROWSが消滅する
];
$query = new WP_Query($args);
// 注意:この場合、$query->found_posts は常に 0 になります
「でも、これじゃページネーションのリンクが作れないじゃないか!」という声が聞こえてきそうですね。その通りです。だからこそ、大規模サイトでは「無限スクロール」や「次へ/前へボタンのみ(全ページ数非表示)」といったUI設計が推奨されるのです。
—
3. 実践:高速ページネーションの実装コード
もしどうしても「全ページ数」が必要なら、`found_posts` を使わずに、必要な時だけキャッシュされた件数を取得するという設計にします。
function get_optimized_post_count($post_type) {
// 頻繁に変わらないならTransients APIでキャッシュする
$count = get_transient(‘my_site_post_count_’ . $post_type);
if (false === $count) {
global $wpdb;
// SQL_CALCを使わず、インデックスが効く範囲でカウントする
$count = $wpdb->get_var($wpdb->prepare(
“SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_type = %s AND post_status = ‘publish'”,
$post_type
));
set_transient(‘my_site_post_count_’ . $post_type, $count, HOUR_IN_SECONDS);
}
return $count;
}
陥りやすい文法エラーと注意点
- `global $wpdb` の使用: 直接クエリを叩くときは必ず `$wpdb->prepare` を使ってください。これを忘れると、SQLインジェクションの脆弱性を生みます。
- キャッシュの生存期間: `set_transient` の時間を長くしすぎると、記事を投稿しても数字が反映されません。`save_post` フックを使って、更新時にキャッシュをクリアするのがプロの作法です。
—
4. 最後に:エンジニアとしての視点
WordPressは非常に柔軟ですが、その「何でも簡単にできる」という甘美な仕様が、実はパフォーマンスを殺す諸刃の剣でもあります。
- 小規模なら標準機能で十分。
- 大規模なら、標準の「便利機能」をあえて切り捨てる勇気を持つ。
これが、WordPressという巨大なエコシステムと付き合っていくための、唯一の正解です。
今日学んだ `no_found_rows` を使って、一度ご自身のサイトのクエリログを `Query Monitor` プラグインで覗いてみてください。驚くほどクエリの実行時間が短縮されていることに気づくはずです。
ここをクリアすれば、あなたはもうWordPressの「利用者」から「設計者」へと一歩踏み出せたということです。素晴らしい成長ですね。また次の深い場所でお会いしましょう。