web-dev-qa-db-ja.com

一時ループがカスタムループに対して機能しない

私はWordPressテーマで働いています。おすすめの投稿、関連する投稿、最近の投稿を含むウィジェットなどを表示する必要があるので、複数のカスタムループを使用する必要があります。このため、データベースクエリの数も増えました。

パフォーマンスを向上させるためにテーマを最適化するために、私は出会った http://codex.wordpress.org/Transients_API 、これは良い方法のようです。ページをリロードするたびに更新する必要がないというループをキャッシュします。

これまでのところ非常に良いことに、私はwp_nav_menuにtransientを使いましたが、それは本来のように機能しました。 dbクエリの数を少し減らすことができました。

カスタムループにトランジェントを使用しようとしたときに問題が発生しました。

トランジェントが保存されます。過渡値を取得することができます。唯一の問題は、データベースクエリの数が、トランジェントなしでWP_Queryを使用する場合よりもかなり多いように思われることです。

これが私のカスタムループです。

if( false === ( $loop = get_transient('featured') ) ) {
    $loop = new WP_Query( array( 'posts_per_page' => 20 ) );
    set_transient('featured', $loop, 60 * MINUTE_IN_SECONDS);
}

if( $loop->have_posts() ) :

    while( $loop->have_posts() ) : $loop->the_post();

        the_title();
        the_post_thumbnail('thumb');

    endwhile;

endif;
wp_reset_postdata();

データベースクエリの数と実行時間を表示するために使用されるコードは次のとおりです。

<?php echo get_num_queries(); ?> queries in <?php timer_stop(1); ?> seconds.

クエリデバッグプラグインを使用すると、update_meta_cache()によって多くのクエリが生成されることがわかります。

なぜデータベースクエリの数が減少するのではなく増加するのか、そしてなぜこれがメニューのために機能したのか説明できませんが、カスタムループのためには機能しませんでした。たぶん私は何かを逃した。任意の助けは大歓迎です。

2
Marius

私は昨日実際にポストに取り組みました(ここでそれをチェックしてください)、そして同じ問題に見舞われました。私はまた トランジェントAPI にも慣れていません。

ここでの問題は、特定のループに対して、トランジェントの外側で特定の値を使用する必要があることです。あなたは単に間違った値を保存しているだけなので、このためにdbヒットの過負荷が発生しています。

説明すると、これは私が言及した答えからのコードの一部です。これらのカテゴリに属する​​投稿タイトルを含むカテゴリのリストを作成する必要があります。これを達成するために、私は私のカスタムクエリを実行し、それから私のリストを作成するために$qの値を使います

    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

これは私に6 queries in 0.06348 secondsを与えます。

さて、コーデックスからの例を見れば、new WP_Queryの結果を一時的なものにするべきです。私がそうすれば、結果は完全に混乱しています

<?php
if( false === ( $query = get_transient('custom_query') ) ) {
    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 
 set_transient('custom_query', $query, 60 * MINUTE_IN_SECONDS);
}
    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();


?>

上記のコードでは、私の結果はこの31 queries in 0.19141 secondsのようになります。これは25クエリ以上であり、約0.13秒以上かかります。これは、投稿ごとに一時的に保存されていないため、Wordpressは投稿ごとに、その投稿が属するカテゴリを取得するためにデータベースにアクセスする必要があるためです。 25追加のクエリは私のデータベース内の投稿の数です。つまり、間違った情報を保存することによって、実際に多くのリソースを無駄にしているのです。 new WP_Queryからの情報は必要ありませんが、$ qからの結果/値は必要ありません。

そのため、トランジェントを適切に利用するには、正しい値を保存する必要があります。これを行うには、完全なクエリをトランジェントに追加して、それが一度だけ実行されるようにする必要があります。それが、トランジェントが作成されるときです。その後、カスタムクエリは必要なくなり、冗長になります。保存する必要があるのは、$qという値だけです。そのため、トランジェントが作成された後にカスタムクエリを削除し、$qの値だけを保存するようにクエリを変更する方法があります。

念のために言っておきますが、テスト目的で一時的な名前を変更し、時間とクエリを表示しています。トランジェントを作成するときには、値(この場合は$q)を使用する必要があることにも注意してください。

 if ( false === ( $q = get_transient( 'category_list' ) ) ) {

    $args = array( 
        'posts_per_page' => -1
    );

    $query = new WP_Query($args); 

    $q = array();

    while ( $query->have_posts() ) { 

        $query->the_post(); 

        $a = '<a href="'. get_permalink() .'">' . get_the_title() .'</a>';

        $categories = get_the_category();

        foreach ( $categories as $key=>$category ) {

            $b = '<a href="' . get_category_link( $category ) . '">' . $category->name . '</a>';    

        }

        $q[$b][] = $a; // Create an array with the category names and post titles
    }


    /* Restore original Post Data */
    wp_reset_postdata();

set_transient( 'category_list', $q, 12 * HOUR_IN_SECONDS );
}

これは私に2 queries in 0.00195 secondsを与えます。私がトランジェントを効果的に利用した方法がわかります。たくさんの値の配列である$qが私のリストを作成するために利用可能になりました、そしてそれは私の目標を達成するために私に2デシベルのヒットを要する

私はこれがすべて理にかなっていると思います

2
Pieter Goosen

あなたのコードに3つの問題があります

  1. あるDBクエリを使用して別のDBクエリを保存します。 postテーブルの代わりに一時的な値を問い合わせます。これは速くても遅くなくてもかまいませんが、DBとの通信によるペナルティを節約することはできません。

  2. オブジェクトを一時的なものやオプションに保存しないでください。ドキュメントの値によると、スカラのみが想定されているため、get_transientはコードで失敗します。 wp_queryがスキップしてコードの残りの部分のパフォーマンスに影響を与える可能性があることの重要な部分の1つは、返されたpostオブジェクトをキャッシュに格納することによるキャッシュプライミングです(このコンテキストではcacheはセッションキャッシュの寿命が短い)

  3. キャッシュする正しい方法は、生成されたHTMLをキャッシュすることです。あなたのコードは1つのクエリを保存しようとしますが、あなたがHTMLをキャッシュするならばあなたはさらに40を節約するでしょう

0
Mark Kaplun