arbeite mit einer Wordpress-Website, die die folgende Abfrage ausführt, aber ich sehe, dass diese Abfrage viele innere Joins ausführt und die Website lange braucht, um geladen zu werden, und viel herunterkommt, und ich habe versucht, eine Abfrage zu erstellen, die produziert das gleiche Ergebnis, aber noch ohne Erfolg
Ich würde gerne wissen, was könnte ein besserer Weg, dies zu tun
%Vor%Hier ist die EXPLAIN-Ausgabe.
%Vor% Es scheint, dass Sie versuchen, eine Ergebnismenge mit einer Zeile pro Beitrag vom Typ car
zu erhalten. Es scheint, dass Sie verschiedene Attribute jedes Autos in der Post anzeigen möchten, und diese sind in postmeta
verstaut.
Pro-Tipp: Nie verwenden Sie SELECT *
in der Software, es sei denn, Sie wissen absolut, warum Sie es tun. Insbesondere bei Abfragen, die viele JOIN
-Operationen enthalten, gibt SELECT *
viele sinnlose und redundante Spalten zurück.
Es gibt einen Abfrage-Design-Trick für die WordPress postmeta
-Tabelle. Wenn Sie ein bestimmtes Attribut erhalten möchten, tun Sie dies:
Es ist sehr wichtig, dieses Muster zu verstehen, wenn man das tut, was man versucht. Dieses Muster ist erforderlich, weil postmeta
ein spezieller Tabellentyp ist, der als Schlüssel / Wert-Speicher bezeichnet wird. Was ist denn hier los? Ein paar Dinge:
posts
und einem bestimmten Attribut aus der Tabelle postmeta
. LEFT JOIN
in der Tabelle postmeta
, so dass Sie immer noch eine Zeile erhalten, wenn das Attribut fehlt. postmeta
. Hier ist postmeta AS color
. meta_key
(hier ist es 'color' = color.meta_key
) in die ON
-Zustand des Joins ein. SELECT
-Klausel einen Alias, um das Element postmeta.meta_value
mit einem geeigneten Spaltennamen darzustellen. Hier ist color.meta_value AS color
. Sobald Sie sich daran gewöhnt haben, dieses Muster zu verwenden, können Sie es mit einer Kaskade von LEFT JOIN
-Operationen stapeln, um so viele verschiedene Attribute zu erhalten.
Ich habe bei dieser Abfrage eine Reihe von Einrückungen vorgenommen, um das Muster leichter zu erkennen. Möglicherweise bevorzugen Sie einen anderen Einzugsstil.
Es ist schwer zu wissen, warum Sie Leistungsprobleme mit der Abfrage in Ihrer Frage hatten. Das liegt möglicherweise daran, dass Sie eine kombinatorische Explosion mit allen INNER JOIN
-Operationen erhalten haben, die dann gefiltert wurden. Aber auf jeden Fall gab die Abfrage, die Sie zeigten, wahrscheinlich keine Reihen zurück.
Wenn Sie immer noch Leistungsprobleme haben, erstellen Sie einen zusammengesetzten Index für postmeta
in den Spalten (post_id, meta_key, meta_value)
. Wenn Sie ein WordPress-Plugin erstellen, ist das wahrscheinlich eine Aufgabe, die Sie bei der Installation des Plugins erledigen müssen.
Dies ist eine Wordpress-Datenbank, und Sie werden möglicherweise nur ungern umfangreiche Änderungen am Schema vornehmen, da dies in der Zukunft andere Teile der Anwendung beschädigen oder Upgrades verkomplizieren könnte.
Die Schwierigkeit dieser Abfrage zeigt eine der Schattenseiten der Entity-Attribut-Wert Design. Dieses Design ist insofern flexibel, als es erlaubt, neue Attribute zur Laufzeit zu erzeugen, aber es macht eine Menge von Abfragen gegen solche Daten komplexer, als dies bei einer herkömmlichen Tabelle der Fall wäre.
Das Schema für Wordpress wurde nicht gut optimiert. Es gibt einige naive Indexierungsfehler, sogar in der aktuellsten Version 4.0.
Für diese bestimmte Abfrage helfen die folgenden zwei Indizes:
%Vor% Der bk1
Index hilft dabei, genau den richtigen Metaschlüssel und Wert zu finden.
Der bk2
Index hilft dabei, den Filesort zu vermeiden.
Diese Indizes können keine Indizes abdecken, da post_title
und meta_value
TEXT
Spalten sind und diese zu lang sind, um vollständig indiziert zu werden. Sie müssten sie in VARCHAR(255)
ändern. Das birgt jedoch die Gefahr, dass die Anwendung beschädigt wird, wenn sie längere Strings in dieser Tabelle speichert.
Um das Leistungsproblem mit 10+ Joins SQL-Abfragen in innodb-Tabellen mit utf8-Zeichensatz zu lösen, erstellen Sie einen neuen Index für postmeta:
Datenbank zuerst sichern. Reduzieren Sie [wp_]postmeta.meta_key
length auf 191, um zu vermeiden, dass " Angegebener Schlüssel zu lang war; maximale Schlüssellänge ist 767 Byte " Fehler.
ALTER TABLE wp_postmeta MODIFY meta_key VARCHAR(191);
Index erstellen
CREATE INDEX wpm_ix ON wp_postmeta (post_id, meta_key);
Für die Leistung versuchen Sie:
Geben Sie explizit die Spalten an, die Sie ziehen möchten. Sehen Sie, welche Indizes Sie benötigen oder nicht. Begrenzen Sie die Anzahl der gezogenen Zeilen.
ist das besser?
%Vor%Wenn es immer noch langsam ist, was wahrscheinlich der Fall ist, versuchen Sie, diesen Index hinzuzufügen,
%Vor% Sie könnten auch versuchen, diesen Index zu wp_post
Je mehr Sie die Auswahlliste einschränken können (das Bit zwischen SELECT
und FROM
), desto besser. Es hat keinen Sinn, viele Daten zurückzugeben, die Sie nicht verwenden. Sie erhalten die beste Leistung, wenn die gesamte Auswahlliste von einem Index "abgedeckt" ist.
Tags und Links sql mysql database wordpress inner-join