Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Beim Sortieren nach Datum desc verlangsamt die Verwendung von temporären Abfragen

Ich denke, die meisten Probleme hier und in ähnlichen Fragen resultieren aus einem Missverständnis, wie MySQL (und andere Datenbanken) Indizes zum Sortieren verwendet. Die Antwort lautet:MySQL verwendet keine Indizes zum Sortieren, es kann Daten nur in der Reihenfolge eines Index oder in umgekehrter Richtung lesen. Wenn Sie möchten, dass die Daten in der Reihenfolge des aktuell verwendeten Indexes sortiert werden, haben Sie Glück, ansonsten wird das Ergebnis sortiert (daher filesort in EXPLAIN)

Die Reihenfolge des gesamten Ergebnisses hängt hauptsächlich davon ab, welche Tabelle die erste im Join war. Und wenn Sie sich Ihr EXPLAIN ansehen, werden Sie sehen, dass der Join von der 'log_codes'-Tabelle ausgeht (weil sie viel kleiner ist).

Grundsätzlich benötigen Sie einen zusammengesetzten Index (partner_id, date) für „log_entries“, einen abdeckenden zusammengesetzten Index (log_code, category_overview, log_desc) für „log_codes“, ändern Sie „INNER JOIN“ in „STRAIGHT_JOIN“, um die Join-Reihenfolge zu erzwingen. und sortiere nach 'date' DESC (dieser Index wird glücklicherweise auch abdecken).

UPD1 :Es tut mir leid, ich habe den Index für die erste Tabelle falsch eingegeben:Es sollte (partner_id, log_code, date) sein .

MySQL kann Daten entweder direkt ausgeben, solange Sie mit der Reihenfolge einverstanden sind, in der es sie erhält, oder Daten in eine temporäre Tabelle schreiben, Sortierung anwenden und dann ausgeben. Wenn Sie in Joins nach einem Feld aus einer nicht-ersten Tabelle sortieren, muss MySQL die Daten sortieren (und nicht nur in der Reihenfolge eines Indexes ausgeben) und um die Daten zu sortieren, benötigt es eine temporäre Tabelle.

Um Zeilen 50000,25 auszugeben, muss MySQL sowieso die ersten 50000 abrufen und sie überspringen. Da ich eine Spalte im Index übersehen habe, hat MySQL nicht nur den Index gescannt, sondern für jedes Element zusätzlich auf der Disk nach log_code gesucht Wert. Mit dem übergreifenden Index sollte das viel schneller gehen, da alle Daten aus dem Index geholt werden können.

UPD2 :versuchen, den Index zu erzwingen:

SELECT log_entries.date, log_codes.log_desc
FROM log_entries FORCE INDEX (IX_partner_code_date)
STRAIGHT_JOIN log_codes
  ON log_codes.log_code = log_entries.log_code
WHERE log_entries.partner_id = 1
  AND log_codes.category_overview = 1
ORDER BY log_entries.date DESC;