WordPressのサブループにはnew WP_Query()ではなくget_posts()を使うべき
WordPressのサブループはnew WP_Queryとget_posts()でどちらが処理が速く、パフォーマンスが高いのか確かめてみた
以前、wordpressのサブループについて紹介した記事を書いた。その記事ではnew WP_Queryの方がパフォーマンスが良いと書いたが、ほんとにそうなのか気になったので、今回、この魔王が自ら試してみたぞ。
結論:サブループにはget_posts()を使うべき
結論からいうと、これからはサブループにはget_posts()を使うのがよい。
検証内容や検証結果はこれから下に載せていくが、処理速度に関してはget_posts()とnew WP_Queryをカスタマイズしたもので同じだった。
ではなぜ処理速度が同じなのにget_posts()を勧めるのか?
理由は簡単。get_posts()のほうがシンプルだからである。
なぜ検証したのか
サブループを使う際にget_posts()とnew WP_Queryどちらが適切なのか調べていたら、「サブループはnew WP_Queryをカスタマイズして使うべき」という記事を見つけたのだ。
前回はこの記事を信じてnew WP_Queryをカスタマイズしたものを推したが、しばらくして、「get_posts()は最もシンプルにサブループを作ることができる」という記事も見つけた。
真っ向から違う意見なので、もうこれは魔王自ら検証するしかないと思ったわけだ。
パフォーマンスを検証したサブループ
さて、今回検証したループはこの5つだ。
get_posts()とnew WP_Query() 、10upで推奨されているパラメータを追加したループ3種の計5つ
・new WP_Query() パターン1
・new WP_Query() パターン2
・new WP_Query() パターン3
・new WP_Query() パターン4
・get_posts()
検証に使用した環境はこんな感じである。
wordpressのversionはver5.5.5
約20000記事、カスタムフィールドは各記事約50項目
PHP7.4.13
new WP_Query() パターン1
new WP_Query()をそのまま使用した場合
<?php
$start1 = microtime(true);
$args = array(
'post_type'=>'post',
'posts_per_page' => 100,
'post_status' => array('publish'),
);
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) {
while( $the_query->have_posts() ) {
$the_query->the_post();
the_title();
}
wp_reset_postdata();
}
$end1 = round(microtime(true) - $start1,5);
echo "<p>パフォーマンステスト1</p>";
echo "<p>{$end1} 秒</p>";
?>
パターン1の検証結果
パフォーマンステスト1
0.06304 秒
new WP_Query() パターン2
パラメータに'no_found_rows' => true,を追加した場合
<?php
$start2 = microtime(true);
$args = array(
'no_found_rows' => true,
'post_type'=>'post',
'posts_per_page' => 100,
'post_status' => array('publish'),
);
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) {
while( $the_query->have_posts() ) {
$the_query->the_post();
the_title();
}
wp_reset_postdata();
}
$end2 = round(microtime(true) - $start2,5);
echo "<p>パフォーマンステスト2</p>";
echo "<p>{$end2} 秒</p>";
?>
パターン2の検証結果
パフォーマンステスト2
0.01096 秒
new WP_Query() パターン3
パラメータに以下を追加した場合
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'fields' => 'ids',
<?php
$start3 = microtime(true);
$args = array(
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'post_type'=>'post',
'posts_per_page' => 100,
'post_status' => array('publish'),
'fields' => 'ids',
);
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) {
while( $the_query->have_posts() ) {
$the_query->the_post();
the_title();
}
wp_reset_postdata();
}
$end3 = round(microtime(true) - $start3,5);
echo "<p>パフォーマンステスト3</p>";
echo "<p>{$end3} 秒</p>";
?>
パターン3の検証結果
パフォーマンステスト3
0.01133 秒
new WP_Query() パターン4
パラメータに以下を追加した場合
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
<?php
$start4 = microtime(true);
$args = array(
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'post_type'=>'post',
'posts_per_page' => 100,
'post_status' => array('publish'),
//'fields' => 'ids',
);
$the_query = new WP_Query( $args );
if ( $the_query->have_posts() ) {
while( $the_query->have_posts() ) {
$the_query->the_post();
the_title();
}
wp_reset_postdata();
}
$end4 = round(microtime(true) - $start4,5);
echo "<p>パフォーマンステスト4</p>";
echo "<p>{$end4} 秒</p>";
?>
パターン4の検証結果
パフォーマンステスト4
0.01071 秒
get_posts()
get_postsを使用した場合
<?php
$start5 = microtime(true);
$args = array(
'post_type'=>'post',
'posts_per_page' => 100,
'post_status' => array('publish'),
);
$my_posts = get_posts( $args );
if ( $my_posts ) {
global $post;
foreach( $my_posts as $post ) {
setup_postdata( $post );
the_title();
}
wp_reset_postdata();
}
$end5 = round(microtime(true) - $start5,5);
echo "<p>パフォーマンステスト5</p>";
echo "<p>{$end5} 秒</p>";
?>
get_posts()の検証結果
パフォーマンステスト5
0.01098 秒
検証結果まとめ
//new WP_Query()
0.06304 秒
//new WP_Query()
'no_found_rows' => true,
0.01096 秒
//new WP_Query()
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'fields' => 'ids',
0.01133 秒
//new WP_Query()
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
0.01071 秒
//get_posts()
0.01098 秒
各サブループの比較結果
new WP_Query() パターン1 | 0.06304 秒 | 0.07154 秒 | 0.06243 秒 |
new WP_Query() パターン2 | 0.01096 秒 | 0.01526 秒 | 0.01214 秒 |
new WP_Query() パターン3 | 0.01133 秒 | 0.01524 秒 | 0.01175 秒 |
new WP_Query() パターン4 | 0.01071 秒 | 0.01446 秒 | 0.01187 秒 |
get_posts | 0.01096 秒 | 0.01396 秒 | 0.01179 秒 |
検証結果からみる考察
何回か検証してみたが、結果は変わらなかった。1番大きな違いは、new WP_Query() を使う場合、'no_found_rows' => true,がないと格段に遅くなる。これは間違いない。
なお、get_posts()では'no_found_rows' はtrue以外設定できないようになっているので、get_posts()では設定しなくてよい。
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'fields' => 'ids',
に関しては、設定してもしなくても大きな違いは見られなかった。
つまりサブループを使用するなら、new WP_Query()に'no_found_rows' => trueを設定するか、get_posts()を使うべきだ。
'no_found_rows' => trueを忘れただけで、get_posts()の5〜6倍遅くなる危険があるので、魔王は素直にget_posts()を使用することを勧めるがな!
get_posts()とnew WP_Query() の使い分け
シンプルさと速さにおいてはget_posts()に軍配があがる。
ではnew WP_Query()は使い道がないのかというと、そうではないぞ。
new WP_Query()はget_posts()よりも詳細なデータを取得できる。get_postsで対応できない場合にはnew WP_Query()を使用するがよい。
new WP_Query()とget_posts()で取得できるパラメータがどれくらい違うのかは、株式会社LIGのこの記事がよいであろう。
ここまで違う!WordPressの[WP_Query]と[get_posts()]の特性を暴いてみる
今回参考にした記事
今回は参考というより、検証にいたる原因になった記事である
サブループにはnew WP_Queryを使うべきと書いてある記事
new WP_Queryをカスタマイズして使うべきと書いてある記事は10upというサイト(英語)のこちらの記事である。
翻訳したサイトもこちらで見つけたぞ。日本語で読みたいものはこちらを読むがよいであろう。
この10upというサイトはcssやJS、PHPなどで注意すべき点や改善すべき点を10個ずつ紹介している。
その中でphpのWordpressの項目に
Do not use $wpdb or get_posts() unless you have good reason.
get_posts() actually calls WP_Query, but calling get_posts() directly bypasses a number of filters by default. Not sure whether you need these things or not? You probably don’t.
特に理由がなければ、get_posts()を使うべきではない。get_posts()はWP_Queryを呼び出しているが、呼び出す際にいくつかのフィルターを通している。そのフィルターは実際にはほとんど必要がないものだ。なのでnew WP_Queryを使ったほうが良い。
と書いてある。
あとは HACK NOTEでも「パフォーマンスが上がるかも」と紹介しておるな。
サブループにはget_posts()がベストと書いてある記事
get_posts()がベストと書いてあるのはwordpress.orgのこの記事。
そう公式なのだ。まぁ公式に書いてなかったら今回検証はしなかっただろうがな。
この記事の一番下にこう記載されている。
If you would just like to call an array of posts based on a small and simple set of parameters within a page, then get_posts is your best option.
もし、ページにシンプルに記事を呼び出したいなら、get_posts()がベストな方法である。
とある。
今回自分で検証してみて、やはり公式の情報をまず1番に信用すべきだと改めて思ったな。
今回のまとめ
・サブループを作るならget_posts()が最もシンプルで速い方法
・new WP_Query()はより詳細なデータを取得できる。
・new WP_Query()を使うなら'no_found_rows' => trueを忘れないようにする。