web-dev-qa-db-ja.com

ほとんどの場合、$ wpdb-> get_resultsはWP_Queryより速いですか?

私のホームページには、最後の5つのおすすめ投稿を表示しなければならないセクションがあります。注目投稿は、カスタムフィールドis_featuredを1に設定した投稿です。

私は2つの異なるタイプのコードで欲しいものを達成しました:

Wpdbを使う

<?php    
    $featuredPosts = $wpdb->get_results("
        SELECT ID, post_title FROM $wpdb->posts
        LEFT JOIN $wpdb->postmeta ON($wpdb->posts.ID = $wpdb->postmeta.post_id)
        WHERE $wpdb->postmeta.meta_key = 'is_featured'
        ORDER BY ID DESC LIMIT 5
    ");

    if ($featuredPosts)
    {
        $htmlOutput = '';                   

        foreach ($featuredPosts as $featPost)
            $htmlOutput .= '<br /><a href="'.get_permalink($featPost->ID).'">'.$featPost->post_title.'</a>';
    }

    echo $htmlOutput;
?>


"Query Monitor"プラグインによると、このクエリは0.1秒かかり、次のSQLを生成します。

SELECT ID, post_title
FROM wp_posts LEFT JOIN wp_postmeta ON(wp_posts.ID = wp_postmeta.post_id)
WHERE wp_postmeta.meta_key = 'is_featured'
ORDER BY ID DESC
LIMIT 5


Wordpressのネイティブコールを使う

<?php                                                                       
    $featuredPostsRevised = new WP_Query
    (
        array
        (
            'meta_query' => array
            (
                array
                (
                    'key' => 'is_featured'
                )
            ) 
        ) 
    );  

    while($featuredPostsRevised->have_posts()) : $featuredPostsRevised->the_post();
?>
        <br />
        <a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a>
<?php
    endwhile;
?>


"Query Monitor"プラグインによると、このクエリは0.2秒かかり、どういうわけか長いSQLを生成します。

SELECT SQL_CALC_FOUND_ROWS wp_posts.ID
FROM wp_posts
INNER JOIN wp_postmeta
ON (wp_posts.ID = wp_postmeta.post_id)
WHERE 1=1
AND wp_posts.post_type = 'post'
AND (wp_posts.post_status = 'publish'
OR wp_posts.post_status = 'private')
AND (wp_postmeta.meta_key = 'is_featured' )
GROUP BY wp_posts.ID
ORDER BY wp_posts.post_date DESC
LIMIT 0, 10

私の質問は:

  1. wpdbクエリをどのようにprepare()することができますか?私は試したが、2番目のパラメータのために管理できませんでした。

  2. Prepareを使用した後、セキュリティとパフォーマンスの観点から、wpdbが本当に良い解決策であると私は思っていますか?

3
WPRookie82

どうやってwpdbクエリをprepare()できますか?私は試したが、2番目のパラメータのために管理できませんでした。

prepare()の動作は Codex で説明されています。プレースホルダとそのプレースホルダを置き換える追加の引数を持つクエリが必要です。プレースホルダがない(つまりクエリ内に可変部分がない)場合は、 esc_sql を使用してSQLインジェクションを回避できますが、これはクエリがユーザ入力を使用して構築されている場合にのみ意味があります。 OPのクエリは完全にハードコードされているので、prepare()esc_sql()の必要はありません。

Prepareを使用した後、セキュリティとパフォーマンスの観点から、wpdbが本当に優れたソリューションであると私は思っていますか?

簡単な答え: いいえ WP_Queryは、クエリに対する単なる上位レベルのアプローチです。クエリ文字列を作成し、$wpdbを使用してデータベース内でそのSQLクエリを実行します。

OPで2つのクエリを見た場合、たとえば、$wpdbを使用して実行されたクエリは投稿ステータス、投稿日、または投稿パスワードを考慮に入れていません。それらはユーザーに表示されます。また、クエリは結果の順序やその他のものを考慮に入れていません。すべてを考慮に入れた複雑なクエリ文字列を構築してから$wpdbを使用して実行できるのであれば、2つの可能性があります。

  1. ループが必要になるたびに、複雑なハードコードされたクエリ文字列を記述してください。
  2. 柔軟な方法でクエリを処理するコードをいくつか書いてください:それは非常に難しいので、WP_Queryにすでにcoreで処理されている多くのコードを書くべきです:それは意味がありません。

考慮すべきもう1つの重要な要素があります:WP_Queryはかなりたくさんの フィルタとアクションフック を起動します、そして何千ものプラグインとテーマはそれらに頼ります:ループのためのmanual$wpdbクエリを実行することによってたくさんのことを破る。

そのため、postsをクエリする必要がある場合はWP_Queryを使用します。数ミリ秒は何時間ものコードやフラストレーションの価値がありません。 $wpdbは、コアで処理されていないクエリを実行する必要がある場合にのみ使用してください。

ここに @TomJNowell を追加する価値があります。

また、WP_Queryを使用すると、WordPressが保持している大量の内部キャッシュを利用できるようになります。たとえば、2度目にクエリを実行した場合などに1回検索したりできます。たぶん、あなたはおそらくあなたの仕事をするためにジョブキューかCLIスクリプトを使うべきです(あなたがたった10人のユーザーとたくさんのお金をサーバーに費やすのでなければ)。

7
gmazzap