MySQL Sehr langsame Abfrage beim Ändern eines Wofeldes trotz keiner Index/Schlüssel

dba.stackexchange https://dba.stackexchange.com/questions/3780

  •  16-10-2019
  •  | 
  •  

Frage

Dies ist ein ziemlich verwirrendes Problem für mich. Ich habe eine Datenbank voller Baseballstatistiken. Ausführen dieser Abfrage:

SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN games ON games.gameName = hits.gameName
WHERE games.type = 'R'
LIMIT 50

Kehrt zurück:

/* 0 rows affected, 50 rows found. Duration for 1 query: 0.218 sec. */

Aber diese Frage ausführen:

SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN games ON games.gameName = hits.gameName
WHERE games.leagueLevel = 'mlb'
LIMIT 50

Hängt lange. Der Index in der Spieltabelle ist nur Spiele. Gamenname und sonst nichts.

Wählen Sie einen unterschiedlichen Typ von Spielen aus, die 8 Einzelcharakterzeilen (VARCHAR 1) einschließlich eines Nulls ergeben.

Wählen Sie unterschiedliche Leagelevel aus Spielen aus, die 6 Zeilen mit drei Zeichen (VARCHAR 5) einschließlich eines Nulls ergeben.

Ich habe keine Ahnung, warum die zweite Frage außerordentlich langsam sein würde, während der erste in Ordnung läuft.

Danke für Ihre Hilfe.

War es hilfreich?

Lösung

Standpunkt Nr. 1: Sie müssen viele einen Blick auf die Spaltenwertpopulation werfen

SELECT COUNT(1) rowount,type FROM games GROUP BY type WITH ROLLUP;
SELECT COUNT(1) rowcount,leaguelevel FROM games GROUP BY leaguelevel WITH ROLLUP;

Aus Ihrer Frage sammle ich zwei Dinge:

  1. Die Anzahl der Zeilen in Spielen mit Typ = 'R' muss eine niedrige Zahl gegen die Anzahl der Zeilen in der Spieltabelle sein.
  2. Die Anzahl der Zeilen in Spielen mit Leagelevel = 'MLB' muss eine hohe Zahl (mehr als 5% der Tabelle) gegen die Anzahl der Zeilen in der Spieltabelle sein. (5% ist eine Faustregel in den Augen von Abfragungsoptimierern)

Standpunkt Nr. 2: Möglicherweise müssen Sie diese Abfrage neu refaktorieren

Beachten Sie, dass die Abfrage den Where -Teil ausführen wird, nachdem alle Verbindungen abgeschlossen sind. Wenn der Ort früher durchgeführt werden könnte, könnte dies dazu beitragen, die Zeit zu verkürzen. Versuchen Sie, die Abfrage wie folgt neu zu organisieren:

SELECT * FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN (SELECT * FROM games WHERE leagueLevel = 'mlb') games
ON games.gameName = hits.gameName
LIMIT 50;

Standpunkt Nr. 3: Rufen Sie nur die Spalten ab, die Sie wirklich benötigen

Ich sehe, Sie haben ausgewählte * und Sie haben vier Tabellen (Treffer, Stadien, Spieler, Spiele). Sie haben viele doppelte Daten, die Sie in die Abfrage ziehen können, insbesondere beim Ziehen der Spalte der Spiele aus allen vier Tabellen.

Sie sollten die Abfrage neu organisieren, um nur eine Spalte für Spiele zu bringen:

SELECT hits.gameName,hits.*,players.*,staduims.*,games.* FROM hits
JOIN stadiums ON stadiums.gameName = hits.gameName
JOIN players ON (players.gameName = hits.gameName AND players.id = hits.batter)
JOIN (SELECT * FROM games WHERE leagueLevel = 'mlb') games
ON games.gameName = hits.gameName
LIMIT 50;

Wenn Sie nicht jede Spalte aus den Hits -Tabellen benötigen, geben Sie außerdem nur die Spalte an, von der Sie wissen, dass Sie zugreifen werden. Gleiches gilt für Spieler, Stadien und Spiele.

Mit anderen Worten, beispielsweise, wenn Sie den Playername nur aus der Spielertabelle benötigen, brauchen Sie keinen Spieler.* Im Auswählen. Sie brauchen nur Player.playername.

Standpunkt Nr. 4: Möglicherweise müssen Sie die Spalte Leaguelelevel indexieren

Sie müssen Folgendes tun, um den erforderlichen Index zu erstellen:

ALTER TABLE games ADD INDEX (leagueLevel);

Vorher führen Sie dies aus

SELECT COUNT(1) rowcount,leaguelevel FROM games GROUP BY leaguelevel WITH ROLLUP;

Jeder Wert für Leaguelevel, dessen Anzahl größer als 5% der Tabelle beträgt, führt dazu, dass der MySQL -Query -Optimierer den Index nicht verwendet.

Andere Tipps

Ich habe keine Ahnung, warum die zweite Frage außerordentlich langsam sein würde, während der erste in Ordnung läuft.

Sie sind nicht allein - es ist sehr häufig, tiefer in das spezifische Whys und die Ausführung von Abfragen eintauchen zu müssen.

Sie müssen lernen, die verfügbaren Tools zu verwenden, beginnend mit explain und explain extended. Lassen Sie uns wissen, wie Sie aufkommen ...

Sie haben gerade das Glück, dass die erste Abfrage schnell zurückkehrt. Ich stimme @jack douglas zu, benutze Erklärungen, füge die erforderlichen Indizes hinzu und wiederhole, bis sich beide Abfragen verbessern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit dba.stackexchange
scroll top