WordPressのサブループにはnew WP_Query()ではなくget_posts()を使うべき

Last modified date

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() パターン10.06304 秒0.07154 秒0.06243 秒
new WP_Query() パターン20.01096 秒0.01526 秒0.01214 秒
new WP_Query() パターン30.01133 秒0.01524 秒0.01175 秒
new WP_Query() パターン40.01071 秒0.01446 秒0.01187 秒
get_posts0.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を忘れないようにする。

魔王様

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Post comment