Frage

Unsere Umwelt: Drupal + MySQL

gibt das Abfrageprotokoll Prüfungs, dass die folgende Abfrage, die aus node_load Funktion des Drupal Kerns sehr viel Zeit nimmt.

EXPLAIN auf der node_load Abfrage zeigt, dass der Index nicht auf der USER-Tabelle verwendet wird.

mysql> explain SELECT n.nid, n.vid, n.type, n.status, n.created, n.changed, 
    n.comment, n.promote, n.sticky, r.timestamp AS revision_timestamp, r.title, 
    r.body, r.teaser, r.log, r.format, u.uid, u.name, u.picture, u.data 
FROM xyz_node n 
INNER JOIN xyz_users u ON n.uid = u.uid 
INNER JOIN xyz_node_revisions r ON r.vid = n.vid;

+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref          | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
|  1 | SIMPLE      | u     | ALL    | PRIMARY       | NULL    | NULL    | NULL         |  181 |             | 
|  1 | SIMPLE      | n     | ref    | vid,uid       | uid     | 4       | xyz.u.uid |    9 | Using where | 
|  1 | SIMPLE      | r     | eq_ref | PRIMARY       | PRIMARY | 4       | xyz.n.vid |    1 |             | 
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+

Jede Idee, was los sein könnte, und wie ich MYSQL Index zu verwenden, um auf diese Abfrage zwingen könnte?

War es hilfreich?

Lösung

Die Tische sind nicht unbedingt in der Reihenfolge verbunden, dass sie in der FROM-Klausel angegeben werden. In diesem Fall sieht es aus wie MySQL, dass in Ermangelung einer WHERE Klausel in der Abfrage entschieden hat, ist es wahrscheinlich schnellsten zuerst die Benutzer-Tabelle zu scannen, und dann kommen, dass mit den anderen Tabellen.

Das erste, was ich tun würde, wäre ANALYZE TABLE auf allen drei Tabellen in der Abfrage beteiligt laufen. Dies aktualisiert Tabellenstatistiken und gespeicherte Schlüsselverteilung und ermöglicht das Optimierungsprogramm beitreten, um bessere Entscheidungen zu treffen. Führen Sie die EXPLAIN Aussage danach und sehen, ob sie sich geändert hat.

Wenn es sich nicht geändert hat, müssen Sie mit dem STRAIGHT_JOIN Stichwort greifen. Dies zwingt die Join-Optimierer die Tabellen in der genauen Reihenfolge in der Abfrage angegeben beizutreten. Um festzustellen, ob Sie dies tun sollen, sollen Sie das Produkt aller rows Werte aus einem EXPLAIN Ergebnis nehmen, und vergleichen Sie es mit der tatsächlichen Anzahl der Zeilen aus der Abfrage zurückgegeben werden. Also in diesem Fall, zu vergleichen, 1629 (181x9x1) an die tatsächliche Anzahl der Zeilen. Wenn sie signifikant verschieden sind, könnte ein STRAIGHT_JOIN für aufgerufen werden (als Schlüsselwort verwendet, um SELECT, dh. SELECT STRAIGHT_JOIN n.nid ... etc).

Als beiseite, gibt es eine Möglichkeit, um zu sagen einen bestimmten Index zu verwenden, aber ich glaube nicht, dass in dieser Abfrage für Ihre Benutzertabelle funktionieren würde, wie es jetzt ist, da es keine WHERE Klausel ist. Wenn Sie STRAIGHT_JOIN am Ende mit, könnten Sie möglicherweise es brauchen, aber in diesem Fall MySQL würde wahrscheinlich auf dem Primärschlüssel abholen, wenn die Benutzertabelle in der nicht die erste Tabelle war beizutreten.

Sie sollten einen Blick auf die Syntax Seite ERKLÄREN für weitere hilfreiche Informationen über diese auch.

Diese Abfrage sieht nicht, wie es sein sollte , die langsam für das, was es ist. Ohne eine where-Klausel können Sie ein Full-Tisch erwarten irgendwo scannen und MySQL hat es gehalten bis etwa 1700 insgesamt Zeilen nach unten untersucht. Es scheint, als wäre dies nur ein Problem, wenn es sich um eine hochfrequentierte Abfrage war, in dem Fall, dass Sie die zugrunde liegende Architektur untersuchen möchten, die (ohne WHERE Klausel) beinhaltet eine Abfrage ausgeführt wird, die jeden Benutzer im System auswirken wird, und nur erhalten schwerer als mehr Benutzer hinzugefügt werden.

Andere Tipps

Da MySQL nur einen Index pro Tabelle pro Abfrage verwenden kann, als Sie manchmal ein „freies“ Bereich Index-Scan von nur werfen in diesem scheinbar nutzlosen Zustand erhalten können.

WHERE u.uid > 0

Versuchen Sie diese Klausel in dem Hinzufügen, wahrscheinlich der ALL-Table-Scan auf einen "Bereich" ändern wird, was besser als ein Full-Table-Scan ist.

Könnte diese Hilfe?

Im Tabellenknoten, erstellen einen Index auf (uid, vid) ALTER TABLE 'xyz_node' ADD INDEX user_ver ( 'uid' vid‘) (Beachten Sie die zweite Zeile in der Ausgabe erklären .. unter der Rubrik möglichen Schlüssel .. Sie sehen vid, uid)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top