2017-08-30 1 views
1

Ich habe Probleme mit dem Ausführungspfad auf MySQL, was zu langsamen und inkonsistenten Abfragen führt. Dies ist ein brandneues Phänomen. Wir haben andere Tabellen mit genau den gleichen (na ja, so nah wie möglich) Setup, die in Ordnung sind, aber aus irgendeinem Grund hat das Erstellen neuer Tabellen jetzt dieses langsame/inkonsistente Problem.MySql Ausführungspfad variiert plötzlich sehr, ist inkonsistent und langsam

Wir verwenden Version: "Mysql Ver 14.14 Distrib 5.6.31, für Debian-Linux-gnu" mit InnoDB. Die Datenbank lebt in einer vagabundierenden Box.

Das Verhalten wurde an einem anderen Computer reproduziert, und nach brandneuen Versionen der Vagabund-Box.

Wie ich bereits sagte, ist die db in einer Vagabund-Box auf meinem lokalen Computer, und meine Maschine ist nicht unter starker Belastung.

t1 hat etwa 1m Zeilen. t2 ist eine neue Tabelle.

Dies ist die einfachste Abfrage, die konsequent das Problem reproduziert:

SELECT 
    * 
FROM 
    redacted_t1 AS t1 
     JOIN 
    redacted_t2 AS t2 ON t1.a_column = t2.id 
WHERE 
t2.c_column != 'asdff' 
ORDER BY t1.b_column DESC; 

unten einige Beispiele von Ausführungspfaden finden, die langsam (mehr als 3 s)

Ich habe an gesehen mindestens 2 andere Ausführungspfade (die auch langsam waren), aber da es schwer zu reproduzieren ist (zufällig?) kann ich sie hier nicht posten.

Manchmal, aber nicht oft, ich weiß nicht, wie oder warum der folgende Ausführungspfad passiert:

Dies ist sehr schnell, 0,00 s. Manchmal erzeugt eine brandneue Version (wie in einer neuen Landstreicherbox) der Datenbank und das Ausführen von optimize auf t1 und t2 dieses Ergebnis. Manchmal macht die Optimierung nichts. Manchmal wird dieser Ausführungsstatus erreicht, ohne die Tabelle zu optimieren. Beachten Sie, dass die Anzahl der Zeilen für t1 im Vergleich zu den langsamen Ausführungspfaden viel niedriger ist. Dies ist konsistent mit dem, was ich sehe, wenn ich "SHOW STATUS;" ausführen.

CREATE TABLE `redacted_t2` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 

    -- redacted 

    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci 

CREATE TABLE `redacted_t1` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `a_column` int(11) DEFAULT NULL, 

    -- redacted 

    PRIMARY KEY (`id`), 

    -- redacted 

    KEY `redacted_t1_a_column` (`a_column`), 

    -- redacted 

    CONSTRAINT `fk_redacted_t1_2032420404` FOREIGN KEY (`a_column`) REFERENCES `redacted_t2` (`id`), 
) ENGINE=InnoDB AUTO_INCREMENT=redacted DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci 

So habe ich ein paar Fragen:

1) Warum ist der Ausführungspfad so inkonsequent, und warum haben wir das noch nie begegnet?

2) Wie gehen wir vor, dies zu beheben, so dass die Abfrage, die 0,00 s dauern sollte, nicht zufällig 3 s dauert?

Alle Ideen, Vorschläge, Erklärungen sehr geschätzt, danke!

+0

Ihre Screenshots zeigen eine andere Abfrage als der Text in Ihrer Frage. Die Screenshots filtern nach 'b_column' (' t2.b_column! = 'Asdff''), während der Text nach 'c_column' (' t2.c_column! =' Asdff'') filtert. Welches ist richtig? – markusk

+0

Guter Fang. Es spielt keine Rolle, welche Spalte es ist, solange es von der Tabelle t2 stammt. –

+0

Der Grund, warum ich frage, ist sicherzustellen, dass es einen Index für die tatsächlich im Filter verwendete Spalte gibt. Da die DDL in Ihrer Frage weder 'b_column' noch' c_column' enthält, kann ich nicht feststellen, ob die Abfrage nach indizierten Spalten filtert oder nicht. – markusk

Antwort

0

Gelöst.

Offenbar ist der Optimierer ... nicht so toll. Wenn das Optimierungsprogramm Ihre Abfrage nicht verarbeiten kann, machen Sie die Abfrage etwas komplizierter.

Also habe ich eine Spalte der ORDER BY hinzugefügt. Das behebt alles. Nicht ideal, aber aus irgendeinem Grund funktioniert es.

SELECT 
    * 
FROM 
    redacted_t1 AS t1 
     JOIN 
    redacted_t2 AS t2 ON t1.a_column = t2.id 
WHERE 
t2.c_column != 'asdff' 
ORDER BY t1.b_column, t2.id DESC; 
1

Sie können versuchen, EXPLAIN EXTENDED auszuführen, gefolgt von SHOW WARNINGS, um weitere Details über den Abfrageausführungsplan zu erhalten. Details finden Sie unter 8.8.3 Extended EXPLAIN Output Format.

Sie können auch ANALYZE TABLE unter t1 und t2 ausführen, um sicherzustellen, dass MySQL aktualisierte Tabellenstatistiken verwendet, wenn Sie den Ausführungsplan auswählen.

Hinzufügen eines Index auf redacted_t2.c_column könnte helfen, da Sie für diese Spalte filtern.

Von der EXPLAIN Ausgabe scheint MySQL manchmal den Index redacted_t1_a_column nicht zu verwenden. Sie können die Datenbank ermutigen oder zwingen, den Index mit index hints, z. USE INDEX oder FORCE INDEX.

+0

Zeige Warnungen zeigt nichts an, nur Code 1003 (was ich verstehe, ist der Code, EXPLAIN EXTENDED wurde verwendet). ANALYZE TABLE wird ausgeführt, wenn Sie OPTIMIZE TABLE ausführen, was ich versuchte, meine ursprüngliche Frage zu sehen =) Hinzufügen eines Index zu redacted_t2.c_column hilft leider nicht. –

+0

Enthält die 'Message'-Spalte des' SHOW WARNINGS'-Ergebniss etwas Interessantes? – markusk

+0

Es tut es nicht. Nur Ihr Standard-Kram mit entkleideten und umbenannten Spalten in der Auswahl, einem Join, wo und Reihenfolge nach. Ich würde es posten, aber mir steht das nicht frei. Aber es sieht gut aus für mich. –

0
SET innodb_stats_sample_pages = 30; 
ANALYZE TABLE t1; 
ANALYZE TABLE t2; 

Dann sehen Sie, ob es konsistenter ist. Da Sie> 5.6.6 ausführen, sollten die Statistiken "persistent" sein. Verwenden Sie nicht OPTIMIZE TABLE.

Umzug auf, zu optimieren:

Brauchen Sie wirklich alle Spalten aus beiden Tabellen (SELECT *)? Es macht einen Unterschied bei Optimierungen und Indizes. Haben Sie uns alle relevanten Indizes gezeigt? Gibt es TEXT oder BLOB Spalten? Müssen Sie sie holen?

Wie viel Prozent der Tabelle ist t2.c_column != 'asdff'? Wenn es ein kleiner Prozentsatz ist, dann brauchen Sie INDEX(c_column).

Ist t2 nur 5 Zeilen lang? Wenn dies der Fall ist, werden Indizes, Pläne usw. nicht viel ausmachen.

+0

Bitte erklären Sie, wie wichtig der EXPLAIN-Plan und der Index sind, wenn die Zeilen für t2 nur 5 sind? Wie/wo sollte ich dann nach dem Problem suchen? Das t2 ist eine neue Tabelle, so dass es leer ist, manchmal addiere ich bis zu 300 Zeilen, das Verhalten ist das gleiche. –

+0

Die EXPLAIN kann oder darf nicht geändert werden. Auf der Suche nach einer bestimmten Zeile von 5: Die Verwendung eines Index hat einige Overhead der Verwendung des Index; Wenn Sie keinen Index verwenden, müssen Sie die anderen 4 Zeilen überspringen. Der Zeitunterschied ist wahrscheinlich unter einer Millisekunde. (Und ich kann nicht vorhersagen, was schneller wäre.) Für 300 Zeilen ist die indizierte Variante wahrscheinlich schneller. Moral der Geschichte: Es ist gefährlich, die Leistung von kleinen Tischen abzuleiten. –