Content MarketingBezahltes und organisches Suchmaschinenmarketing

WordPress: Fehlerbehebung und Optimierung Ihrer Template-SQL-Abfragen mit SAVEQUERIES

Ein häufiger Grund für eine träge WordPress Die Website ist nicht unbedingt Ihr Host, Ihr CDNoder sogar Ihre Bildgrößen – es ist Ihre Datenbank. Genauer gesagt, das Volumen und die Ineffizienz von SQL Abfragen, die von Ihrem Theme und Ihren Plugins generiert werden. Jeder Seitenaufruf kann Dutzende – oder in schlecht optimierten Fällen Hunderte – von Datenbankabfragen auslösen. Wenn diese Abfragen über Widgets, Shortcodes, Sidebars und Block-Editor-Elemente multipliziert werden, können sie erhebliche Leistungsengpässe verursachen, die unbemerkt bleiben, aber dennoch Ihre Core Web Vitals negativ beeinflussen (CWVund die allgemeine Benutzererfahrung.

Viele Entwickler konzentrieren sich auf Caching und CDN-Auslieferung, um Leistungsprobleme zu kaschieren, doch das löst nur einen Teil des Problems. Ist die zugrundeliegende Abfragelast ineffizient, wird das Problem im Grunde nur überdeckt. Der erste Schritt zu echter Geschwindigkeitsoptimierung besteht darin, zu verstehen, was im Hintergrund passiert.

SPEICHERQUERIE

WordPress bietet eine integrierte Konstante, SAVEQUERIESDieses Protokoll erfasst jede Datenbankabfrage, die während einer Anfrage ausgeführt wird, einschließlich ihrer jeweiligen Dauer. Bei sorgfältiger Anwendung ist es ein unschätzbares Diagnosewerkzeug, um Ineffizienzen in Ihren Theme-Vorlagen, Seitenerstellern und Plugin-Integrationen aufzudecken.

Auf einer gut optimierten WordPress-Website sollte eine typische Seitenvorlage zwischen 20 und 50 Abfragen generieren. Eine minimalistische Startseite oder ein einfaches Layout für einen einzelnen Beitrag liegt eher bei 20, während eine komplexere Archiv- oder WooCommerce-Produktseite aufgrund von Taxonomieabfragen und Metadaten naturgemäß auf fast 50 ansteigen kann.

Alles darüber hinaus – insbesondere Zahlen im dreistelligen Bereich – deutet auf Ineffizienz hin. Jede Abfrage verursacht zusätzlichen Aufwand, und selbst Verzögerungen im Mikrosekundenbereich summieren sich unter Last schnell. Eine hohe Anzahl an Abfragen weist in der Regel auf redundante Schleifen, nicht zwischengespeicherte Optionen oder Plugins hin, die unabhängig von der Hauptabfrage von WordPress eigene Datenbankabfragen ausführen. Niedrige Abfragezahlen bedeuten nicht willkürliche Grenzwerte, sondern sicherzustellen, dass jede Abfrage einen triftigen Grund hat und Ihre Templates auf allen Seiten vorhersehbar funktionieren.

Der Weg zu SAVEQUERIES Auf einer Live-Website ohne Ausgabekontrolle kann dies schnell überfordernd wirken. Tausende von Abfragen tauchen möglicherweise am Ende des HTML-Codes auf, was die Identifizierung der für die Verzögerungen verantwortlichen Templates oder Komponenten erschwert. Die Lösung besteht in der automatisierten Protokollierung, sodass jeder Template-Typ – Startseite, Seite, Einzelbeitrag, Archiv – eine eigene Protokolldatei generiert. Dies ermöglicht eine klare, segmentierte Ansicht der ressourcenintensivsten Abfragen.

So protokollieren Sie Ihre WordPress-Template-Abfragen

Hier ist eine einfache, aber effektive Methode, um WordPress-Abfragen effizient zu protokollieren. Indem Sie den folgenden Code in die functions.php Ihres Themes oder ein benutzerdefiniertes Plugin einfügen, können Sie Abfrageprotokolle automatisch erfassen und speichern, sobald Sie als Administrator angemeldet sind. SAVEQUERIES aktiviert.

// If SAVEQUERIES is enabled, print the queries in the footer in an HTML tag
function log_queries_to_file() {
    global $wpdb;

    // Check conditions: SAVEQUERIES enabled and logged-in admin
    if (defined('SAVEQUERIES') && SAVEQUERIES && is_user_logged_in() && current_user_can('manage_options')) {
        // Define the log directory (site root/queries/)
        $log_dir = ABSPATH . 'queries/';
        
        // Create the directory if it doesn't exist (with recursive creation and proper permissions)
        if (!file_exists($log_dir)) {
            mkdir($log_dir, 0755, true);
        }
        
        // Skip if directory isn't writable
        if (!is_writable($log_dir)) {
            return; // Or add error logging if desired
        }
        
        // Determine the filename based on page type
        $filename = '';
        
        if (is_front_page()) {
            $filename = 'queries-frontpage.log';
        } elseif (is_page()) {
            $template_slug = get_page_template_slug(get_the_ID());
            if (empty($template_slug)) {
                $template_slug = 'default';
            } else {
                // Sanitize template slug: basename without .php
                $template_slug = basename($template_slug, '.php');
            }
            $filename = 'queries-page-' . sanitize_title($template_slug) . '.log';
        } elseif (is_archive()) {
            $post_type = 'post'; // Default for standard archives
            if (is_post_type_archive()) {
                $post_type = get_query_var('post_type');
                if (is_array($post_type)) {
                    $post_type = reset($post_type); // Handle multi-type, take first
                }
            } elseif (is_category() || is_tag() || is_tax()) {
                // For taxonomies, get the post type from queried object if custom
                $queried = get_queried_object();
                if ($queried && isset($queried->taxonomy)) {
                    $tax = get_taxonomy($queried->taxonomy);
                    $post_type = is_array($tax->object_type) ? reset($tax->object_type) : $tax->object_type;
                }
            } elseif (is_author() || is_date()) {
                $post_type = 'post';
            }
            $filename = 'queries-archive-' . sanitize_title($post_type) . '.log';
        } elseif (is_singular()) { // Covers single posts, pages, CPTs
            $post_type = get_post_type(get_the_ID());
            $filename = 'queries-single-' . sanitize_title($post_type) . '.log';
        }
        
        // If no matching type, skip or use a fallback like 'queries-other.log'
        if (empty($filename)) {
            return;
        }
        
        // Full file path
        $file_path = $log_dir . $filename;
        
        // Prepare log content (queries list with optional header)
        $log_content = "\n\n=== Queries for " . esc_url_raw(home_url(add_query_arg(array(), $GLOBALS['wp']->request))) . " on " . current_time('mysql') . " ===\n";
        $log_content .= print_r($wpdb->queries, true);
        
        // Append to file (creates if not exists)
        file_put_contents($file_path, $log_content, FILE_APPEND | LOCK_EX);
    }
}
add_action('shutdown', 'log_queries_to_file');

Nach der Aktivierung finden Sie dort /queries/ Ich habe ein Verzeichnis im WordPress-Stammverzeichnis erstellt, das Protokolldateien wie queries-frontpage.log oder queries-single-post.log enthält. Als Administrator habe ich jede URL aufgerufen, die eine meiner Vorlagen verwendet, um die Abfragen und deren Leistung zu erfassen.

So lesen Sie Ihre SAVEQUERIES-Daten

Jeder Eintrag zeigt den Abfragetext, die Ausführungszeit und den Funktionsaufrufstapel an, der die Abfrage ausgelöst hat. Mit der Zeit erhalten Sie so ein Profil der Vorlagen und Funktionen, die den größten Ressourcenverbrauch verursachen.

[20] => Array
        (
            [0] => SELECT wp_posts.ID FROM wp_posts  LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE 1=1  AND ( wp_term_relationships.term_taxonomy_id IN (32489)
) AND wp_posts.post_type = 'nav_menu_item' AND ((wp_posts.post_status = 'publish')) GROUP BY wp_posts.ID ORDER BY wp_posts.menu_order ASC		 
            [1] => 0.00042486190795898
            [2] => require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), include('/themes/jannah/page.php'), get_header, locate_template, load_template, require_once('/themes/mtz-23/header.php'), TIELABS_HELPER::get_template_part, include('/themes/jannah/templates/header/load.php'), TIELABS_HELPER::get_template_part, include('/themes/jannah/templates/header/nav-top.php'), wp_nav_menu, wp_get_nav_menu_items, get_posts, WP_Query->query, WP_Query->get_posts
            [3] => 1762916659.7638
            [4] => Array
                (
           )
)

Dieser Eintrag aus der SAVEQUERIES-Ausgabe stellt eine einzelne von WordPress ausgeführte SQL-Abfrage dar, zusammen mit Zeit- und Kontextdetails, die es ermöglichen, nachzuvollziehen, wo und warum sie ausgeführt wurde. Jedes nummerierte Array-Element entspricht einer Abfrage, und die Struktur liefert fünf wichtige Informationen:

  1. Die Abfrage selbst — Der Wert an Index [0] ist die rohe SQL-Anweisung, die WordPress an die Datenbank gesendet hat. In diesem Fall:
SELECT wp_posts.ID 
FROM wp_posts  
LEFT JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id)
WHERE 1=1  
  AND (wp_term_relationships.term_taxonomy_id IN (32489))
  AND wp_posts.post_type = 'nav_menu_item' 
  AND ((wp_posts.post_status = 'publish')) 
GROUP BY wp_posts.ID 
ORDER BY wp_posts.menu_order ASC
  1. Diese Abfrage ruft alle veröffentlichten Navigationsmenüpunkte (post_type = 'nav_menu_item') ab, die zu einem bestimmten Menüpunkt (term_taxonomy_id = 32489) gehören. Der LEFT JOIN verknüpft jeden Menüpunkt mit seinen Taxonomiebeziehungen, und die GROUP BY- und ORDER BY-Klauseln stellen sicher, dass die Menüpunkte in der definierten Reihenfolge zurückgegeben werden. Dies ist eine typische Abfrage, die generiert wird, wenn ein WordPress-Theme ein Navigationsmenü über wp_nav_menu() rendert.
  2. Ausführungszeit der Abfrage Der Wert an Index [1] (0.00042486190795898) gibt die Ausführungszeit der Abfrage in Sekunden an. In diesem Fall wurde sie in weniger als einer halben Millisekunde abgeschlossen, was hervorragend ist. Bei der Überprüfung der Protokolle sind Abfragen, deren Ausführungszeit regelmäßig 0.02–0.05 Sekunden überschreitet, potenzielle Optimierungskandidaten.
  3. Stapel aufrufen Der Wert an Index [2] listet die vollständige PHP-Aufrufkette auf, die zu dieser Abfrage geführt hat. Von links nach rechts gelesen, zeigt sich, dass die Abfrage vom Header-Template des Themes beim Rendern des Navigationsmenüs stammt. Genauer gesagt rief die Funktion `wp_nav_menu` die Funktion `wp_get_nav_menu_items` auf, welche wiederum einen Aufruf von `get_posts` auslöste, der schließlich von der Methode `WP_Query->get_posts` ausgeführt wurde. Diese Aufrufkette ist unerlässlich, um genau zu ermitteln, welches Template oder welche Funktion die Abfrage initiiert hat.
  4. Timestamp Der Wert an Index [3] (1762916659.7638) ist ein Unix-Zeitstempel, der den Zeitpunkt der Abfrageausführung während der Anfrage markiert. Dies hilft, Abfragen chronologisch zu ordnen oder sie bestimmten Ladesequenzen zuzuordnen.
  5. Argumente — Das letzte Array bei [4] ist in diesem Beispiel leer, würde aber alle gebundenen Parameter enthalten, wenn die Abfrage Platzhalter verwenden würde.

Zusammenfassend zeigt dieser Logeintrag, dass das Theme eine Standardabfrage generiert hat, um Navigationsmenüpunkte für die Anzeige im Seitenkopf abzurufen. Obwohl die Abfrage selbst effizient ist, verdeutlicht sie, dass jeder Menüpunkt oder dynamische Abschnitt zusätzliche Abfragen auslösen kann. Auf komplexen Seiten mit mehreren Menüs oder Widget-basierten Kopfzeilen können sich diese kleinen, wiederholten Abfragen summieren – was die Bedeutung des Caching von Menüs und anderen statischen Seitenelementen als effektive Optimierungsstrategie unterstreicht.

So optimieren Sie Ihre Vorlagen und Abfragen

Sobald Sie die Templates und Komponenten identifiziert haben, die die meisten Anfragen generieren, geht es im nächsten Schritt darum, diese zu optimieren. Bei der Anfrageoptimierung in WordPress geht es nicht nur um Geschwindigkeit, sondern auch um Stabilität und Skalierbarkeit. Mit wenigen gezielten Anpassungen lässt sich die Anzahl der Anfragen deutlich reduzieren, sodass Ihre Seiten auch bei hohem Besucheraufkommen reaktionsschnell bleiben.

  1. Unnötige Anfragen eliminierenViele WordPress-Themes und -Plugins greifen auf Daten zu, die sie gar nicht benötigen. Beispielsweise laden manche alle Metadaten eines Beitrags, obwohl nur ein Feld benötigt wird, oder rufen `get_posts()` innerhalb von Schleifen auf, anstatt die Hauptabfrage zu verwenden. Überprüfen Sie Ihre Template-Dateien und entfernen Sie redundante Datenbankabfragen, insbesondere innerhalb von Schleifen oder in wiederkehrenden Komponenten wie Headern und Footern. Ersetzen Sie nach Möglichkeit datenbankgesteuerte dynamische Inhalte durch statische Template-Tags oder vorab berechnete Werte.
  2. Reduzieren Sie das Abfragevolumen durch Caching.Eine der effektivsten Methoden zur Effizienzsteigerung ist das Zwischenspeichern häufig abgerufener, sich selten ändernder Informationen. Beispielsweise können Menüs, Widget-Bereiche oder Website-Optionen in temporären Objekten oder im Objektcache zwischengespeichert werden, um wiederholte Abfragen bei jedem Seitenaufruf zu vermeiden. Ein Website-Menü könnte beispielsweise abgerufen und in einem temporären Objekt gespeichert werden, das nur aktualisiert wird, wenn sich das Menü selbst ändert. Dieser Ansatz verlagert wiederkehrende Abfragen und reduziert die Datenbanklast erheblich, ohne die Aktualität der Daten zu beeinträchtigen.
  3. Optimieren Sie die Datenbank durch geeignete Indizierung.Mit der Zeit wachsen WordPress-Datenbanken und werden fragmentiert, insbesondere auf Websites mit umfangreichen Postmeta- oder Kommentarmeta-Tabellen. Das Hinzufügen geeigneter Indizes für häufig abgefragte Spalten – wie meta_key und meta_value – kann hier einen großen Unterschied machen. Viele Plugins, darunter Query Monitor und WP-Optimize, können langsame Abfragen hervorheben und Verbesserungsvorschläge für die Indizierung unterbreiten. Die regelmäßige Optimierung Ihrer Tabellen und das Entfernen verwaister Daten tragen ebenfalls dazu bei, dass MySQL Abfragen effizienter verarbeitet.
  4. Nutzen Sie Datenbank-Caching-ToolsSobald Ihre Abfragen so effizient wie möglich sind, kann das Zwischenspeichern ihrer Ergebnisse die Performance deutlich steigern. Objekt-Caching-Systeme wie Redis oder Memcached speichern Abfrageergebnisse und PHP-Objekte im Arbeitsspeicher, sodass WordPress sie abrufen kann, ohne wiederholt auf die Datenbank zugreifen zu müssen. Dies ist besonders effektiv für stark frequentierte Websites oder solche mit komplexen Abfragemustern, bei denen dieselben Postmeta- oder Taxonomie-Abfragen in mehreren Anfragen erfolgen. Persistentes Objekt-Caching stellt sicher, dass die Daten nach dem Abruf schnell verfügbar bleiben, bis sie explizit ungültig gemacht werden – dies reduziert die MySQL-Last erheblich und verbessert die Antwortzeiten. Viele moderne Hosting-Anbieter bieten die Integration von Redis oder Memcached an, und WordPress unterstützt diese nativ über einfach zu installierende Caching-Plugins wie object-cache.php.
  5. Nutzen Sie Seitencaching- und CDN-ToolsNeben Verbesserungen auf Datenbankebene verhindern Full-Page-Caching-Lösungen, dass viele Seiten überhaupt WordPress oder MySQL aufrufen. Plugins wie WP Rocket, W3 Total Cache und LiteSpeed ​​Cache können statische Versionen Ihrer Seiten generieren und speichern, um sie Besuchern sofort bereitzustellen. Auf Serverebene erzielen Nginx FastCGI Cache oder Varnish denselben Effekt mit noch geringerem Aufwand. Die Integration eines Content Delivery Networks (CDN) wie Cloudflare oder BunnyCDN optimiert dies zusätzlich, indem es diese statischen Assets global zwischenspeichert und verteilt und so die Latenz für Nutzer unabhängig von ihrem Standort minimiert. CDNs können außerdem vollständige HTML-Snapshots für anonyme Besucher zwischenspeichern, wodurch Ihr Ursprungsserver dynamische Anfragen nur selten verarbeiten muss. Zusammen bilden diese Caching-Ebenen eine hierarchische Struktur – Datenbank-Cache, Objekt-Cache, Seiten-Cache und CDN-Cache –, die sicherstellt, dass WordPress Seiten so schnell wie möglich ausliefert und gleichzeitig die Anzahl der Abfragen und die Serverlast drastisch reduziert.

Fazit

Die Datenbankperformance ist einer der am meisten vernachlässigten Aspekte der WordPress-Optimierung. Obwohl Plugins, Skripte und Bilder oft für lange Ladezeiten verantwortlich gemacht werden, sind häufig übermäßige und ineffiziente Datenbankabfragen die eigentlichen Ursachen. Durch Aktivieren von SAVEQUERIES, Protokollierung der Abfragedaten nach Template und systematische Behebung von Problembereichen lassen sich Ineffizienzen aufdecken, die den meisten Entwicklern verborgen bleiben.

Durch das Eliminieren unnötiger Abfragen, intelligentes Caching, die Optimierung Ihrer Tabellen und die Implementierung mehrschichtiger Caching-Lösungen können Sie WordPress von einer abfrageintensiven Anwendung in eine benutzerfreundliche Umgebung verwandeln. CMS in eine schnelle, skalierbare Publishing-Plattform. Wahre Geschwindigkeit wird nicht allein durch das Kaschieren von Ineffizienzen mittels Caching erreicht – sie beginnt mit dem Verstehen und Beheben der eigentlichen Ursache von Ineffizienz: der Art und Weise, wie Ihre Website mit ihrer Datenbank kommuniziert.

Nach oben-Taste
Menu

Adblock erkannt

Wir sind auf Anzeigen und Sponsoring angewiesen, um Martech Zone Kostenlos. Bitte deaktivieren Sie Ihren Werbeblocker – oder unterstützen Sie uns mit einer günstigen, werbefreien Jahresmitgliedschaft (10 US-Dollar):

Melden Sie sich für eine Jahresmitgliedschaft an