WordPress-Blog mit 30.000 Beiträgen: schlechte Suchleistung


7

Unser WordPress-Blog lief einwandfrei, bis wir ungefähr 30.000 Beiträge importierten. Die Suche auf der Website wurde danach sehr langsam.

Das
Laden einer Seite mit dem Such- und Filter-Widget dauert ungefähr 4 Sekunden.
- 18 Sekunden, um die Suchergebnisse zurückzugeben.

Wichtige Plugins, die wir verwenden:
Benutzerdefinierte Beitragstypen - Wir haben nur einen benutzerdefinierten Beitragstyp, der im Blog verwendet wird.
Erweiterte benutzerdefinierte Felder - Wir haben eine Reihe von benutzerdefinierten Feldern, die durchsucht und gefiltert werden können.

Von uns verwendete Such-Plugins:
Alles durchsuchen - Tags, Autoren und Kommentare sind für die Suche aktiviert. Post-Inhalt, Titel und benutzerdefinierte Felder können standardmäßig durchsucht werden.
Search & Filter Pro - wird verwendet, um unser Such- und Filter-Widget zu erstellen und Filterregeln festzulegen.

Caching:
Wir verwenden Memcache als steckbaren Cache für WP sowie als persistente Cache-Lösung.

Umgebung:
Physischer Server: AWS t2.small; 2 GB Speicher; CPU 1 Kern bis 3,3 GHz
Betriebssystem: Windows Server 2012
Webserver: IIS 8.5
PHP 5.6.22
Wordpress 4.6.1 MySQL 5.6.27 (dedizierte RDS-Instanz)

Wir haben eine ziemlich begrenzte Nutzerbasis und beobachten keine signifikanten Spitzen bei der Nutzung der Serverressourcen sowohl für den App-Server als auch für den DB-Server.

Hier ist die am längsten laufende SQL-Abfrage, die ausgeführt wird, wenn Benutzer eine Suche auf einer Website durchführen:

SELECT SQL_CALC_FOUND_ROWS distinct wp_posts.ID
FROM   wp_posts
       LEFT JOIN wp_postmeta
              ON wp_posts.id = wp_postmeta.post_id
       LEFT JOIN wp_term_relationships AS trel
              ON ( wp_posts.id = trel.object_id )
       LEFT JOIN wp_term_taxonomy AS ttax
              ON ( ( ttax.taxonomy = 'post_tag' )
                   AND trel.term_taxonomy_id = ttax.term_taxonomy_id )
       LEFT JOIN wp_terms AS tter
              ON ( ttax.term_id = tter.term_id )
       LEFT JOIN wp_comments AS cmt
              ON ( cmt.comment_post_id = wp_posts.id )
       LEFT JOIN wp_users AS u
              ON ( wp_posts.post_author = u.id )
WHERE  1 = 1
       AND ( ( wp_posts.id IN (<LIST_OF_POST_IDS>)
               AND (( (( ( wp_posts.post_title LIKE '%searchterm%' )
                          OR ( wp_postmeta.meta_value LIKE '%searchterm%' )
                          OR ( wp_posts.post_content LIKE '%searchterm%' ) ))
                       OR (( tter.name LIKE '%searchterm%' ))
                       OR ( (( cmt.comment_content LIKE '%searchterm%' ))
                            AND cmt.comment_approved = '1' )
                       OR (( u.display_name LIKE '%searchterm%' )) ))
               AND wp_posts.post_type = 'generalpost'
               AND (( wp_posts.post_status = 'publish' )) )
             AND post_type != 'revision' )
       AND post_status != 'future'
ORDER  BY wp_posts.post_date DESC
LIMIT  0, 15;

In der Wordpress DB-Dokumentation finden Sie eine Schema-Referenz

Diese Abfrage ist für etwa 65% der Ladezeit der Suchergebnisseite verantwortlich (12 von 18 Sekunden).

Derzeit haben wir nur einen benutzerdefinierten Beitragstyp, und nur dieser muss durchsuchbar sein. Jeder benutzerdefinierte Beitragstyp enthält 18 Datensätze in wp_postmeta. Von diesen 18 Feldern müssen nur 4 durchsuchbar sein - und dies ist eine mögliche Möglichkeit, die Suche zu beschleunigen.

In meinen Tests diese Klausel hinzufügen

`AND meta_key in ('cust_field1', 'cust_field2', 'cust_field3', 'cust_field4',)`

beschleunigte die Abfrage tatsächlich fast zweimal. Plugin-Entwickler wurden kontaktiert, um eine Funktion zur Unterstützung des Ausschlusses von Metafeldern zu implementieren.

Ich habe auch einen zusammengesetzten Index für die Spalten post_id, meta_key und meta_value erstellt, der die Abfragezeit um weitere 5-10% verkürzt .

Was wären die anderen Möglichkeiten, um die Suche mit dieser Datenmenge effizienter zu gestalten, damit die Benutzererfahrung nicht beeinträchtigt wird?


4
Dies ist eine Meinung: Die Volltextsuche von WordPress ist immer weniger effizient und langsamer als eine dedizierte Suchlösung. Probieren Sie ElasticSearch, Google Site Search, Swiftype oder Algolia aus.
Florian

Antworten:


1

Es hört sich so an, als wären Sie bereits auf dem richtigen Weg, fügen zusätzliche Indizes hinzu und optimieren die Abfrage. Ich habe festgestellt, dass die EXPLAINSyntax von MySQL hilfreich ist und mir einen guten Eindruck davon gibt, wo in der Abfrage möglicherweise Fehler auftreten.

Auf hoher Ebene scheint es, dass die Abfrage viele verknüpfte Tabellen, LIKEVergleiche (mit Platzhaltern) und ORKomparatoren enthält, die alle symptomatisch für potenziell weniger leistungsfähige Abfragen sind. Ich würde sicherstellen, dass jede dieser Spalten ordnungsgemäß indiziert ist (insbesondere diejenigen, die normalerweise nicht abgefragt werden), und prüfen, ob Sie dort etwas verpasst haben.

Die Gesamtgröße der Datenbank kann in einigen Umgebungen ein Faktor sein. Zu einem bestimmten Zeitpunkt beschwerte sich eine Client-Site über eine langsame Leistung (nicht nur über die Suche), und wir stellten fest, dass die Indizes daran erstickten, dass etwa 20% der Datenbank aus Post-Revisionen bestand (dies war eine tägliche News-Site, also Revisionen) auf einen Beitrag von vor sechs Monaten war nicht wirklich relevant). Revision Strike entstand aus diesem Bedürfnis heraus und hatte einen großen Einfluss auf die allgemeine Leistung sowie auf die Leistung der Suchseite.

Eine weitere Option, die in Betracht gezogen werden sollte, basiert auf einer spezielleren Suchtechnologie. ElasticPress (vollständige Offenlegung: Ich arbeite für 10up, den Betreuer von ElasticPress) bindet Elasticsearch in WordPress-Abfragen ein, wodurch die Belastung Ihres Webservers erheblich reduziert wird und kompliziertere Suchvorgänge möglich werden (wie Sie es anscheinend mit Ihren Such-Plugins tun). .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.