2009-08-15 17 views
3

Ich habe eine Abfrage in MySQL (in einer gespeicherten Prozedur verwendet), die nach Namen und einem anderen Feld sucht. Wenn ich verschiedene Kombinationen dieser Suchparameter verwende, bekomme ich schnelle Ergebnisse (zwischen 1 und 2s), aber mit einigen bestimmten Werten, bekomme ich eine Abfrage, die 9s dauert, um Ergebnisse auf der Produktionswebseite zurückzugeben. Das folgende ist das, was ich aus der EXPLAIN-Anweisung bekam:Langsame MySQL-Abfrage

id, select_type, table, type, possible_keys, key,  key_len, ref, rows, Extra 
-------------------------------------------- 
1, SIMPLE,  Names, ref, IX_Name,  IX_Name, 17,  const, 3173, Using where 

Namen als varchar deklariert wird (40) und das andere Feld ist Unsigned smallint (6). Ich verwende einen Index für die ersten 15 Zeichen des Namens (IX_Name), der in der Abfrage verwendet wird. Ich kann sehen, dass die langsamen Abfragen in der Spalte "rows" der EXPLAIN-Ausgabe eine recht große Anzahl von Zeilen abrufen.

Ich bin mir nicht sicher, was ich tun kann, um die Leistung zu verbessern. Gibt es irgendeinen merklichen Fehler mit dem obigen EXPLAIN-Ausgang?

Danke, Tim

+2

Es könnte eine gute Idee sein, die langsam ausführende Abfrage zu posten. – karim79

+1

Können Sie Ihre SQL-Anweisung anzeigen? Es kann auch nützlich sein, die Kardinalität der in Ihrer Tabelle gespeicherten Namen zu kennen. – DBMarcos99

Antwort

3

Wie haben Sie füllen den Tisch? Indizes sind Baumstrukturen und um effizient arbeiten zu können, müssen sie ausgewogen sein - was automatisch geschieht, wenn die Tabelle im Batch geladen wird oder die regelmäßige Wartung angewendet wird. Wenn keine dieser Bedingungen zutrifft, ist der Index für diejenigen Teile des Baumes, die übermäßig gewachsen sind, wesentlich weniger effizient.

Einfachste Überprüfung ist es, den Index zu löschen und neu zu erstellen. Wenn Sie danach dasselbe Verhalten haben, ist es etwas anderes, aber das ist zumindest eine Möglichkeit, die eliminiert wurde.

+0

Hallo Cruachan. Danke für Ihre Antwort. Ich habe einen MYISAM 4 Millionen Row Tisch und ich aktualisiere ihn ungefähr jede Woche. Wenn ich eine Aktualisierung (von ungefähr 2000 Reihen jede Woche) mache, führe ich dann die folgenden Aussagen aus: alter table names order by namennummer desc; Optimieren Sie Tabellennamen; Analysieren Tabellennamen; aber ich ändere nicht den Index oder neu erstellen ... könnte das das Problem sein, wie Sie sagten, dass der Index möglicherweise unausgewogen ist? Denn das würde erklären, warum es nur bei bestimmten Namen vorkommt. Danke, Tim –

+0

Es wäre es wert, den Index fallen zu lassen und es neu zu versuchen. Ich habe noch nie eine große MySQL-Datenbank DBA gemacht, also habe ich keine direkte Erfahrung, aber das trifft sicherlich auf einige sehr große Oracle-Datenbanken zu, die ich zum Verwalten verwendet habe. Im Allgemeinen konzentrieren sich die Leute auf die Tabellenstruktur und vergessen, dass Indizes auch Speicherstrukturen sind und auch verwaltet werden sollten. – Cruachan

+0

Wenn Sie das tun, würde ich es schätzen, wenn Sie das Ergebnis zurückgeschickt haben. – Cruachan

1

Okay, Sie haben einen Index auf einem Präfix. Sie verwenden die ersten 15 Zeichen, aber wir so tun, als Sie verwendet nur 1, und Ihre Tabelle werden diese Werte für Namen hatte:

Al Barb Beth Betsy Bill Biff Bob Bonny Buck Bud Carl

Da mein Index nur auf das erste Zeichen steht, muss die Datenbank alle Zeilen lesen, die der Index zurückgibt, und jeden vollständigen Namen mit dem Prädikat vergleichen.

Jetzt, wenn ich nach 'Al' suche, gibt mein Index eine Reihe zurück. Ich vergleiche dann "Al" im Préikat mit "Al" in der Reihe, und ich habe eine Übereinstimmung, also gebe ich diese Reihe zurück, und ich bin fertig.

Wenn ich nun nach 'Alex' suche, gibt mein Index eine Zeile zurück. Ich vergleiche dann "Alex" im Prize mit "Al" in der Reihe, und ich habe kein Match und keine weiteren potenziellen Matches, und ich bin fertig.

Aber wenn ich nach 'Bud' suche (oder irgendetwas, das mit 'B' beginnt), gibt mein Index neun Zeilen zurück. Ich muss neun Zeilen lesen und mit dem Prädikat vergleichen, bevor ich fertig bin.

tun:

select substring(name, 1, 15), count(*) 
from names 
group by substring(name, 1, 15); 

Ich glaube, Sie Ihre schnelle Lookups haben einzigartig finden, während die langsamen sind, wo viele Namen einen gemeinsamen Präfix teilen.

+0

Danke für deine Antwort ... Die Sache ist, ich suche nach dem vollständigen Namen (Fischer), also denke ich nicht, dass das Präfix ein Problem ist, da es sowieso weniger als 15 Zeichen ist ... Und ich denke das Namen sind nach 15 Zeichen fast einmalig. Danke, Tim –

0

Ich finde 3173 Zeilen eine ziemlich große Anzahl zu betrachten, vorausgesetzt, Sie möchten sie an einen Benutzer rendern. Wenn die tatsächliche Anzahl der abgerufenen Datensätze wesentlich kleiner ist, sollten Sie in Betracht ziehen, weitere Indizes zu erstellen. Es wäre nützlich zu wissen, was EXPLAIN für einen anderen Suchbegriff ausgibt.

2

Es scheint, dass Ihre Abfrage nur den Index für ein Feld verwendet. Sie haben erwähnt, dass Sie nach Name und "einem anderen Feld" suchen. MySQL (außer in sehr aktuellen Versionen unter bestimmten Umständen) ist auf einen Index pro Tabellenvorkommen in einer Abfrage beschränkt. Dies bedeutet, dass MySQL, wenn Sie einen Index für name und und index für das andere Feld haben, wahrscheinlich raten muss, welcher Index am hilfreichsten ist und den anderen ignoriert. Es scheint, dass eine bessere Abfragestruktur oder Indexdefinition hilfreich wäre. Wenn Ihr Name ziemlich eindeutig ist und Sie 3.000 Zeilen im EXPLAIN-Plan bekommen, dann sind entweder die Metadaten in der DB nicht gut oder Sie haben eine Menge anderer Möglichkeiten auf dem anderen Feld.

Können Sie die Abfrage und das Schema für die Tabelle bereitstellen?

Sind Ihre Abfragen immer schnell oder immer langsam für die gleiche SQL? Wenn Sie zum Beispiel nach Fisher suchen, ist es schnell und manchmal langsam oder konsistent. Wenn sie konsistent sind, liegt dies wahrscheinlich an der CPU- oder Festplattenaktivität. Wenn Variable, ist es wahrscheinlich auf andere Abfragen in der DB zurückzuführen.

Je nach dem, was Sie auswählen, wenn Sie Ihr vollständiges Ergebnis in einen Index erhalten, wird Ihre Abfrage fliegen, da es die Festplatte nicht schlagen muss, um die Datensätze zu überprüfen. Ich habe ziemlich erstaunliche Verbesserungen mit "Verwenden von Index" -Abfragen gehabt.

Jacob