So optimieren Sie die WP-Site für Millionen von Posts

19

Ich arbeite an einer Website für ein Unternehmen, das höchstwahrscheinlich Millionen von Posts über einen benutzerdefinierten Post-Typ erstellen wird. Es sind Gebete, also gibt der Benutzer am Frontend einfach eine kurze Phrase über ein Formular ein. Alles, was das Unternehmen interessiert, ist der Inhalt des Beitrags und das Datum der Veröffentlichung. Die Seite ist noch nicht einmal online und sie hat bereits über 120.000 Posts, also meine ich es ernst, wenn ich Millionen sage.

Also, ein paar Optimierungsfragen:

  1. Nehmen wir an, ich habe eine Kategorie, die in einem benutzerdefinierten Beitragstyp mit 500.000 Beiträgen 'vorkommt'. Die vorgestellte Kategorie hat nur 500 Beiträge. Wenn ich eine Abfrage für die vorgestellten Posts erstelle, frage ich dann die gesamten 500.000 Posts oder nur die 500 vorgestellten Posts ab? Was ist, wenn ich nur die zehn neuesten Posts anzeigen möchte, die vorgestellt werden?
  2. Wenn ich diesen benutzerdefinierten Beitragstyp in der Datenbank speichere, kann ich dann noch etwas tun, um Serverressourcen zu sparen, zumal der Inhalt des Beitrags und das Datum das einzige sind, was wirklich benötigt wird?
  3. Sollte ich überhaupt einen benutzerdefinierten Beitragstyp verwenden? Ich mag es im Prinzip, weil es gut in den WordPress-Admin integriert ist, aber wenn es signifikante Performance-Nachteile gibt, kann ich wahrscheinlich etwas anderes machen.

Ich habe noch nie an einem Projekt in dieser Größenordnung gearbeitet, daher ist mir die Leistung ein bisschen wichtiger als gewöhnlich. Danke für jede Hilfe!

Jeremiah Prummer
quelle
Es ist wichtig, Datenbankabfragen in Ihren WordPress-Funktionen und Aufrufen von Skripten auf ein Minimum zu beschränken, aber ein großer Teil der Optimierung hat damit zu tun, wie der Server eingerichtet und konfiguriert ist. Suchen Sie dazu im Server-Fehler-Netzwerk. serverfault.com/search?q=optimize+wordpress
iyrin
@RyanLoremIpsum - danke für den Kommentar, aber ich hatte gehofft, Antworten auf meine spezifischen Fragen zu finden. Das meiste, was ich dort gefunden habe, befasst sich mit dem Server selbst, nicht mit der Funktionsweise von WordPress und der Optimierung aus Code-Sicht
Jeremiah Prummer,

Antworten:

25

1. Legen Sie die Abfrage fest, bevor WP_Query ausgeführt wird

Dies scheint das Wichtigste zu sein, das Sie beachten sollten, wenn Sie versuchen, Datenbankabfragen auf ein Minimum zu beschränken, da die Abfrage nur geändert werden kann, bevor sie in der SQL-Datenbank ausgeführt wird.

Normale Abfragen
Für eine normale Abfrage verwendet WordPress die wp()Funktion, die wiederum aufruft $wp->main( $query_vars ). Die "is_-Variablen" aus bedingten Tags werden vor der Übergabe festgelegt WP_Query->get_posts(), wodurch sie in eine MySQL-Datenbankabfrage konvertiert und schließlich im $ wp_query-Objekt gespeichert werden. Es ist möglich, die Abfrage zu filtern, bevor sie tatsächlich in der SQL-Datenbank ausgeführt wird .

Die pre_get_postsAktion greift in diesen Prozess ein und ermöglicht es Ihnen, die Abfrage zu ändern, bevor sie an übergeben wird WP_Query->get_posts().

Wenn Sie beispielsweise die Abfrage nach Beiträgen in der Kategorie "Hervorgehoben" filtern möchten, verwenden Sie add_action( 'pre_get_posts', 'your_function_name' );das in_categorybedingte Tag und schließen es in dieses ein your_function_name.

function your_function_name( $query ) {
    if ( $query->in_category( 'featured' ) && $query->is_main_query() ) {
        // Replace 123 with the category ID of the featured category.
        $query->set( 'cat', '123' );
    }
}
add_action( 'pre_get_posts', 'your_function_name' );

Siehe Plugin-API / Aktionsreferenz / Vorabrufen von Beiträgen «WordPress Codex

Seite Requests
Was Seitenvorlagen, wie die Archivseite für die „vorgestellten “ -Kategorie, bedingte Tags werden nicht funktionieren , aus dem pre_get_postsFilter. Sie können beispielsweise nicht is_categoryzum Überprüfen der Archivseite verwenden, da WP_Query nicht ausgeführt wurde.

Stattdessen müssten Sie die Hauptabfrage für Seitenanfragen mit einer ändern, die ungefähr new WP_Queryso aussieht $query = new WP_Query( 'cat=123' );. Dadurch wird die Abfrage von Anfang an mit dem entsprechenden Argument ausgeführt.

Siehe Klassenreferenz / WP-Abfrage «WordPress-Codex

2. In der Datenbank speichern

Sie können den Filter verwenden, um wp_insert_post_datasicherzustellen, dass nur die für Ihren benutzerdefinierten Beitragstyp relevanten $ -Daten an zurückgegeben werden wp_insert_post. Stellen Sie sicher, dass Sie eine bedingte Anweisung einschließen, um Ihren benutzerdefinierten Beitragstyp zu überprüfen.
Plugin API / Filter Reference / WP Post-Daten einfügen «WordPress Codex

Dieser Hook wird von der wp_insert_postFunktion aufgerufen, die von wp_update_post aufgerufen wird, wenn Sie Ihren benutzerdefinierten Beitragstyp aktualisieren, normalerweise durch Speichern eines Entwurfs oder Veröffentlichen des Beitrags.

Sie müssen es jedoch selbst bewerten, da ich nicht persönlich über die Optimierungsbedeutung der Reduzierung der in der Datenbank aktualisierten Daten sprechen kann.

3. Beeinträchtigen benutzerdefinierte Beitragstypen die Leistung?

Nach meiner Erfahrung sind benutzerdefinierte Beitragstypen ein leistungsstarkes Tool für die Verwaltung von Inhalten. Ich kenne keine andere Möglichkeit, Beiträge so zu verwalten, dass weniger Ressourcen verbraucht werden. Ich würde mich persönlich darauf konzentrieren, Wege zu finden, um die Anzahl der gestellten Anfragen zu verringern, wo immer dies möglich ist.

Früher gab es ein Leistungsproblem im Zusammenhang mit der Permalink-Struktur, das einen Treffer verursachte, wenn mit Text anstelle einer Zahl begonnen wurde. 3 Dies war besonders für Websites mit einer großen Anzahl von Seiten problematisch, wurde jedoch seit WordPress Version 3.3 behoben.

Ich rufe hier nur Permalinks auf, weil der Slug normalerweise der erste Teil der Permalink-Struktur ist, der die Leistung vor Version 3.3 möglicherweise beeinträchtigt hat oder nicht. Abgesehen davon sind mir keine Leistungsprobleme bekannt, die sich aus der Verwendung benutzerdefinierter Beitragstypen ergeben.

Andere Leistungsoptionen

Transienten
Dies ist kein Ersatz, um Abfragen in Ihrem Code auf ein Minimum zu beschränken. Sie können jedoch set_transient verwenden , um die Abfragen für einige Zeit zu speichern, sodass keine neuen Abfragen erforderlich sind. Hier ist das Beispiel, das in Dave Clements 'Post verwendet wird . Beachten Sie auch, dass er empfiehlt, eine save_postAktion hinzuzufügen , um den Übergang jedes Mal zu löschen, wenn ein bestimmter Beitragstyp aktualisiert wird.

<?php // IN THE SPOTLIGHT QUERY
if( false === ( $its_query = get_transient( 'its_query' ) ) ) {
    $pttimestamp = time() + get_option('gmt_offset') * 60*60;
    $its_query = new WP_Query( array(
        'post_type' => 'spotlight',
        'posts_per_page' => 1,
            'post__not_in' => $do_not_duplicate,
        'meta_query' => array(
            array(
                'key' => '_hpc_spotlight_end_time',
                'value' => $pttimestamp,
                'compare' => '>'
            )
        )
    ) );
    set_transient( 'its_query', $its_query, 60*60*4 );
}
if( have_posts() ) { // HIDE SECTION IF NO CURRENT ITS FEATURE ?>
    // LOOP GOES HERE: NOT IMPORTANT TO EXAMPLE
<?php } ?>

Weitere Optimierung von Abfragen
Thomas Griffin hat einige gute Tipps in seinem Tutorial zur Optimierung von WordPress-Abfragen . Hier ist eine kurze Liste seiner Vorschläge:

  • In 'cache_results' => falseeinmaligen Abfragen festlegen, wenn Ihr Server kein persistentes Caching wie Memcached verwendet. Einmalige Abfragen werden als "Abfragen" bezeichnet, die zum Anzeigen kleiner Datenmengen verwendet werden. Möglicherweise möchten Sie nur verknüpfte Beitragstitel für den aktuellen Beitrag anzeigen, oder Sie möchten eine Dropdown-Liste der Beiträge anzeigen, für die Sie auswählen können eine bestimmte Optionseinstellung. "

    Sein Beispiel: $query = get_posts( array( 'posts_per_page' => 1, 'cache_results' => false ) );

  • Stellen Sie ein, 'no_found_rows' => truewo keine Paginierung erforderlich ist. Dadurch wird "MySQL umgangen, indem die Ergebnisse gezählt werden, um festzustellen, ob eine Paginierung erforderlich ist oder nicht".

    Sein Beispiel: $query = new WP_Query( array( 'posts_per_page' => 1, 'no_found_rows' => true ) );

  • Abfrage für Post - IDs nur , wenn dies alles , was Sie brauchen 'fields' => 'ids' in get_posts. Dies sollte die Menge der zurückgegebenen Daten erheblich reduzieren, was pro Post ziemlich viel ist, wenn man sich die Datenbankbeschreibung «WordPress Codex» ansieht

    Sein Beispiel: $query = get_posts( array( 'posts_per_page' => 1, 'fields' => 'ids' ) );

Zusätzlich zu diesem letzten Tipp kann dieselbe Argumentation angewendet werden, wenn Sie mit get_post_field nur ein oder mehrere Post-Felder benötigen .

Ein solides Verständnis der Funktionsweise der Abfrage ist von wesentlicher Bedeutung. Je genauer Sie mit Ihren Abfragen umgehen können, desto weniger Arbeit wird von Ihrer SQL-Datenbank verlangt. Dies bedeutet, dass es eine Vielzahl von Möglichkeiten gibt, Datenbankabfragen zu verwalten. Seien Sie vorsichtig mit benutzerdefinierten Abfragen, sofern diese ausgeführt werden (handelt es sich um eine Administrationsseite?), Verwenden Sie bei direkten Abfragen die ordnungsgemäße Bereinigung und versuchen Sie, native WordPress-Funktionen zu verwenden, mit denen Sie die gleiche Leistung erzielen.

Iyrin
quelle
2
Ausgezeichnete und äußerst hilfreiche Antwort, danke!
Jeremiah Prummer
Das Theme ist komplett maßgeschneidert, so dass wir buchstäblich nur die absolut wesentlichen Elemente abfragen. Diese sind jedoch äußerst hilfreich. Vor diesem Hintergrund gehe ich noch einmal durch und nehme einige Änderungen an meinen Abfragen vor. ;)
Jeremiah Prummer
1
Ich möchte hinzufügen, dass Sie Meta-Abfragen nach Möglichkeit vermeiden sollten. Führen Sie auf keinen Fall eine Abfrage für zwei Metafelder gleichzeitig aus. Dies führt zu doppelten und dreifachen Abfragen, die schnell zu einem Leistungsproblem werden. Benutzerdefinierte Beitragstypen können dabei häufig hilfreich sein.
Charles Jaimet
3

Ich füge auch hinzu:

    'no_found_rows'          => true,
    'update_post_term_cache' => false,
    'update_post_meta_cache' => false,
    'cache_results'          => false
  • no_found_rows (boolean) - mache es wahr, wenn du keine Paginierung benötigst und nicht die Anzahl der gefundenen Beiträge benötigst.
  • cache_results (boolean) - Posten Sie den Informations-Cache.
  • update_post_meta_cache (boolean) - Posten Sie den Metainformationscache.
  • update_post_term_cache (boolean) - Cache für Informationen nach dem Ausdruck.

Wenn Sie diese Parameter verwenden und Werte als FALSE übergeben, können Sie die Abfrage beschleunigen, indem Sie einige zusätzliche Datenbankabfragen stoppen, die ausgeführt werden.

Hinweis: Wir sollten diese Parameter nicht immer verwenden, da das Hinzufügen von Dingen zum Cache die richtige Vorgehensweise ist. Diese können jedoch unter bestimmten Umständen nützlich sein und Sie sollten in Betracht ziehen, sie zu verwenden, wenn Sie wissen, was Sie tun.

Bitte besuchen Sie: https://drujoopress.wordpress.com/2013/06/27/how-to-optimize-wordpress-query-to-get-results-faster/#more-184

Rigosan
quelle
1
Bitte bearbeiten Sie Ihre Antwort und fügen Sie eine Erklärung hinzu: Warum könnte dies das Problem lösen?
fuxia
Ich kann meinen Kommentar zu dieser Antwort nicht hinzufügen: wordpress.stackexchange.com/a/166699/57674
rigosan
1

Wie alle vorzeitigen Optimierungsfragen kann diese nicht wirklich beantwortet werden, ohne die genauen Verwendungsmuster zu kennen, die zu oft erst beim Start entdeckt werden.

Generell sollte es laut MYSQL-Spezifikation keine Probleme mit der Datenmenge geben. Natürlich ist das Durchsuchen von Daten selbst mit den besten Algorithmen langsamer als mit viel kleineren Tabellen, aber die Lösung dafür ist eine einfache, stärkere CPU.

Möglicherweise möchten Sie optimieren, wie Metadaten gespeichert werden (z. B. um keine Ping-bezogenen Daten zu speichern), aber dies hängt davon ab, was Sie genau tun. Letztendlich benötigen Sie möglicherweise noch eine stärkere CPU, sodass sich Ihre Mühe möglicherweise nicht lohnt .

Mark Kaplun
quelle