【入門編】初心者向け:なぜ「no_found_rows = true」にするだけでページネーションが高速化するのか – WordPress 内部コア・データベース構造とパフォーマンス最適化解析バイブル

こんにちは!WordPressの裏側の仕組みやデータベースの挙動に興味を持ってくれて嬉しいです。他の言語からWordPressに入ってきた開発者の中には、「なんか記事一覧を表示するコードを書いたら動いたけど、裏で何が起きているのかいまいち分からないな…」と感じている人も多いのではないでしょうか。

今回は、WordPressのパフォーマンスチューニングにおいて「知っているか、知らないかで雲泥の差が出る」超重要パラメータである `no_found_rows => true` について、データベースの内部構造まで踏み込んで分かりやすく解説していきますね。

ここをクリアすれば、あなたも「ただWordPressを使えるエンジニア」から「裏側の仕組みまでコントロールできるフルスタックエンジニア」に一歩近づけますよ。一緒にマスターしていきましょう!

—

1. なぜページネーション(分割表示)はデータベースに負担をかけるのか?

ブログやニュースサイトを作るとき、1ページあたり10件ずつ記事を表示して、「次のページへ」進めるページネーション機能は必ずと言っていいほど実装しますよね。

WordPressでこれを行う場合、おなじみの `WP_Query` や `get_posts()` を使って以下のようなコードを書くはずです。

$args = array(
‘post_type’ => ‘post’,
‘posts_per_page’ => 10,
‘paged’ => 2, // 2ページ目を表示したい
);
$query = new WP_Query( $args );

このコードが実行されたとき、WordPressの中身(データベース)では何が起きていると思いますか?「たった10件のデータを取ってくるだけでしょ?」と思いますよね。

実は、デフォルトのままだと、MySQLに対して「2回」、あるいは非常にコストの高いクエリが発行されているんです。

デフォルトで発行される2つのSQL

1. メインのデータ取得クエリ:
「今表示すべき10件の記事データを取ってきて!」
2. 総件数のカウントクエリ (`SQL_CALC_FOUND_ROWS`):
「条件に一致する記事は、このブログ全体で全部で何件あるか全部数えてきて!」

この「全部で何件あるか数える」という処理こそが、パフォーマンスを悪化させる諸悪の根源なんです。

—

2. 犯人は `SQL_CALC_FOUND_ROWS` と総件数カウントの裏側

「全部で何件あるか」を数えるために、WordPress(厳密にはMySQL)は内部で `SQL_CALC_FOUND_ROWS` という特別なSQL命令を使っています。

イメージとしてはこんな感じです:

— 実際にMySQL内部で発行されているクエリのイメージ
SELECT SQL_CALC_FOUND_ROWS FROM wp_posts
WHERE post_type = ‘post’ AND post_status = ‘publish’
LIMIT 0, 10;

この `SQL_CALC_FOUND_ROWS` がついていると、MySQLは「LIMITで指定された10件だけ探して終わり」ではなく、「もしLIMIT制限がなかったら、何件ヒットしていたかをわざわざ最後まで数え上げて記憶する」という重い処理を裏で実行します。

データの数が増えると何が起きる?

  • 記事が 100件 のとき:瞬時に終わります。
  • 記事が 10,000件 のとき:少しデータベースが頑張ります。
  • 記事が 100,000件(大規模サイトやECサイトなど) のとき:データベースがすべての行をスキャンしに行くため、ページを表示するたびに数秒の遅延(タイムアウトの原因)が発生します。

「全ページ数(「全100ページ中 2ページ目」など)を表示したい!」という要件がある場合はこの総件数が絶対に必要ですが、「ただの無限スクロールや、古い/新しいの記事一覧ボタン(前へ・次へ)だけで十分」というケースでは、この総件数は完全に無駄な計算になってしまいますよね。

—

3. 救世主 `no_found_rows => true` の使い方とメカニズム

そこで登場するのが、今回の主役である `no_found_rows => true` です。

このパラメータを `WP_Query` の引数に渡してあげると、WordPressはMySQLに対して「総件数を数えるの、もうしなくていいよ!(Skip found rows)」と命令を出してくれます。

具体的なコードの書き方

実装は驚くほど簡単です。`WP_Query` の配列の中に `no_found_rows => true` を追加するだけです。

‘post’,
‘posts_per_page’ => 10,
‘paged’ => get_query_var( ‘paged’ ) ? get_query_var( ‘paged’ ) : 1,
‘no_found_rows’ => true, // ★ここで総件数の取得をスパッと止める!
);

$custom_query = new WP_Query( $args );

if ( $custom_query->have_posts() ) :
while ( $custom_query->have_posts() ) : $custom_query->the_post();
// 記事のループ処理
the_title( ‘

‘, ‘

‘ );
endwhile;
wp_reset_postdata();
else :
echo ‘記事が見つかりませんでした。’;
endif;

たったこれ行(`’no_found_rows’ => true`)を追加するだけで、MySQLは無駄な全件スキャンをしなくなり、今画面に表示する10件のデータだけを最速で取得して帰ってきてくれます。これぞプロのデータベースチューニングですね!

—

4. 初心者がやりがちな「落とし穴」と文法エラー

ここで、「よし、じゃあサイト内のすべてのクエリにこれを入れちゃおう!」と思ったそこのあなた、ちょっと待ってください。ここに初心者がやりがちな大きな罠があります。

⚠️ 注意点:ページャー(総ページ数に基づくページネーション)が動かなくなる

`no_found_rows => true` を設定すると、WordPress側は「総件数(Found rows)」を知ることができなくなります。そのため、以下のような関数を使った「総ページ数に基づくページネーション」が正しく機能しなくなります。

  • `paginate_links()` (「1, 2, 3 … 10」と数字が並ぶページャー)
  • `$wp_query->max_num_pages` を使った判定

💡 どんな場所で使うべき?

  • 「トップページの無限スクロール(ロードモア)」
  • 「サイドバーの『最近の投稿』ウィジェット」
  • 「単なる『もっと見る』ボタンで読み込む一覧」
  • 「全ページ数が画面に表示されない、かつ不要な箇所すべて」

もし「1, 2, 3…」という数字のページネーションを出したいメインのアーカイブページ(`archive.php` や `index.php`)のメインクエリに対してこれを設定してしまうと、ページャーが消えてしまうか、正しく動かなくなるので注意してくださいね。

—

まとめ:ここをクリアすればWordPressの基本はバッチリ!

今回は `no_found_rows = true` を使うだけで、なぜページネーションや記事一覧が高速化するのかを内部のSQLレベルから解説しました。

  • デフォルトでは `SQL_CALC_FOUND_ROWS` が走るため、記事数が多いと重くなる。
  • `no_found_rows => true` を指定すると、総件数のカウントをスキップし、DBの負荷を劇的に軽減できる。
  • ただし、数字のページネーション(`paginate_links`など)が必要な場所では使えないので使い所を見極めること。

WordPressは手軽にサイトを作れる反面、何も考えずにコードを書くと、データベースに無駄な負荷をかけてしまうフレームワークでもあります。「どういうSQLが裏で発行されているか?」を脳内でトレースできるようになると、一気にエンジニアとしてのレベルが上がりますよ。

この知見を武器に、ぜひあなたの開発するWordPressサイトを爆速にチューニングしてみてくださいね!それでは、次のステップでも一緒に楽しく学んでいきましょう。

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