it-swarm.com.de

Stimmt das? $ Wpdb-> get_results ist in den meisten Fällen schneller als WP_Query?

Auf meiner Homepage habe ich einen Bereich, in dem ich die letzten fünf vorgestellten Beiträge anzeigen muss, wobei ein vorgestellter Beitrag einfach ein Beitrag mit einem benutzerdefinierten Feld is_featured ist, das auf 1 gesetzt ist.

Ich habe mit zwei verschiedenen Arten von Codes erreicht, was ich will:

Wpdb benutzen

<?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;
?>


Laut dem "Query Monitor" -Plugin benötigt diese Abfrage 0.1s und generiert diese 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


Verwenden der systemeigenen Aufrufe von 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;
?>


Laut dem "Query Monitor" -Plugin benötigt diese Abfrage 0.2s und generiert ein etwas längeres 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

Meine Fragen sind:

  1. Wie kann ich prepare() meine wpdb abfragen? Ich habe es versucht, konnte es aber aufgrund des zweiten Parameters nicht schaffen.

  2. Habe ich nach der Verwendung von prepare Recht, wenn ich davon ausgehe, dass wpdb in Bezug auf Sicherheit und Leistung in der Tat eine bessere Lösung ist?

3
WPRookie82

Wie kann ich meine wpdb-Abfrage vorbereiten ()? Ich habe es versucht, konnte es aber aufgrund des zweiten Parameters nicht schaffen.

Die Funktionsweise von prepare() wird in Codex erläutert. Sie benötigen eine Abfrage mit Platzhaltern und zusätzlichen Argumenten, um diese Platzhalter zu ersetzen. Wenn Sie keine Platzhalter (also keine variablen Teile in der Abfrage) haben, können Sie esc_sql verwenden, um SQL-Injections zu vermeiden. Dies ist jedoch nur dann sinnvoll, wenn die Abfrage mithilfe von Benutzereingaben erstellt wird. Die Abfrage in OP ist vollständig fest codiert, sodass weder prepare() noch esc_sql() erforderlich sind.

Habe ich nach der Verwendung von prepare Recht, wenn ich davon ausgehe, dass wpdb in Bezug auf Sicherheit und Leistung tatsächlich eine bessere Lösung ist?

Kurze Antwort: nein . WP_Query ist nur ein Ansatz auf höherer Ebene für Abfragen. Er erstellt eine Abfragezeichenfolge und verwendet dann $wpdb, um diese SQL-Abfrage in der Datenbank auszuführen.

Wenn Sie sich 2 Abfragen in OP ansehen, die unterschiedlich sind, berücksichtigt die Abfrage, die mit $wpdb ausgeführt wurde, nicht den Poststatus, das Postdatum oder das Postkennwort. Wenn Sie also geplante oder private Posts mit der ersten Abfrage gelöscht haben, wird dies nicht berücksichtigt Sie werden Benutzern angezeigt. Die Abfrage berücksichtigt auch nicht die Reihenfolge der Ergebnisse und andere Dinge. Natürlich können Sie eine komplexe Abfragezeichenfolge erstellen, die alles berücksichtigt, und diese dann mit $wpdb ausführen. Sie haben zwei Möglichkeiten:

  1. schreiben Sie jedes Mal, wenn Sie eine Schleife benötigen, eine komplexe, fest codierte Abfragezeichenfolge: Dies ist wirklich überwältigend und fehleranfällig
  2. schreiben Sie Code, der flexibel mit Abfragen umgeht: Es wird sehr schwierig, und Sie sollten eine Menge Code schreiben, der bereits von Core in WP_Query verarbeitet wird: Das macht keinen Sinn.

Ein weiterer wichtiger Faktor ist zu berücksichtigen: WP_Query löst ziemlich viele Filter- und Aktions-Hooks aus, und Tausende von Plugins und Themes stützen sich darauf: Wenn Sie eine manuelle$wpdb-Abfrage für Schleifen ausführen, werden Sie brechen viele Dinge.

Wenn Sie also posts abfragen müssen, verwenden Sie WP_Query: Einige Millisekunden sind Stunden und Stunden Code und Frustrationen nicht wert. Verwenden Sie $wpdb nur, wenn Sie Abfragen ausführen müssen, die nicht von core verarbeitet werden.

Es lohnt sich, @TomJNowell hier zu kommentieren:

Beachten Sie auch, dass Sie mit WP_Query viele der in WordPress gespeicherten internen Caches nutzen können, z. B. das einmalige Abrufen eines Posts, wenn er ein zweites Mal abgefragt wird usw. Wenn Sie 50.000 Posts gleichzeitig abfragen müssen Sie sollten wahrscheinlich eine Jobwarteschlange oder ein CLI-Skript verwenden, um Ihre Arbeit zu erledigen (es sei denn, Sie haben nur zehn Benutzer und viel Geld für einen Server).

7
gmazzap