2012-03-30 12 views
8

Ich habe eine MySQL-Tabelle mit über 30 Millionen Datensätze, die ursprünglich mit Myisam gespeichert wurde. Hier ist eine Beschreibung der Tabelle:Leistungsunterschied zwischen Innodb und Myisam in Mysql

describe_table

ich die folgende Abfrage dieser Tabelle führen würde, die im Allgemeinen etwa 30 Sekunden dauern würde abzuschließen. Ich würde @eid jedes Mal ändern, um Datenbank- oder Platten-Caching zu vermeiden.

select count(fact_data.id) 
    from fact_data 
    where [email protected] 
     and fact_data.metric_id=1 

ich konvertiert dann diese Tabelle innoDB ohne weitere Änderungen vornehmen und anschließend die gleiche Abfrage gibt jetzt unter einer Sekunde jedes einzelne Mal, wenn ich die Abfrage zulaufen. Selbst wenn ich zufällig @eid einstelle, um Zwischenspeichern zu vermeiden, kehrt die Abfrage in weniger als einer Sekunde zurück.

Ich habe die Unterschiede zwischen den beiden Speichertypen untersucht, um zu versuchen, die dramatische Verbesserung der Leistung zu erklären, aber ich konnte mir nichts einfallen lassen. Tatsächlich deutet vieles von dem, was ich lese, dass Myisam schneller sein sollte.

Die Abfragen, die ich ausführe, sind gegen eine lokale Datenbank, bei der zum Zeitpunkt der Tests keine anderen Prozesse die Datenbank erreichen.

Antwort

15

Das ist ein überraschend großer Leistungsunterschied, aber ich kann mir ein paar Dinge vorstellen, die dazu beitragen können.

MyISAM wurde in der Vergangenheit als schneller als InnoDB angesehen, aber für neuere Versionen von InnoDB gilt das für eine viel, viel kleinere Reihe von Anwendungsfällen. MyISAM ist in der Regel schneller für Tabellen-Scans von schreibgeschützten Tabellen. In den meisten anderen Anwendungsfällen finde ich InnoDB normalerweise schneller. Oft um ein Vielfaches schneller. Tabellensperren sind ein Todesstoß für MyISAM in den meisten meiner Verwendung von MySQL.

MyISAM speichert Indizes in seinem Schlüsselpuffer. Vielleicht haben Sie den Schlüsselpuffer zu klein eingestellt, um den Index für Ihre etwas größere Tabelle effektiv zwischenzuspeichern.

MyISAM hängt vom Betriebssystem ab, um Tabellendaten aus den .MYD-Dateien im Betriebssystemdatenträgercache zwischenzuspeichern. Wenn das Betriebssystem nicht mehr genügend Arbeitsspeicher zur Verfügung hat, beginnt es seinen Plattencache zu entladen. Das könnte es zwingen, weiter von der Platte zu lesen.

InnoDB speichert beide Indizes und Daten in einem eigenen Speicherpuffer. Sie können das Betriebssystem anweisen, seinen Festplattencache auch nicht zu verwenden, wenn Sie innodb_flush_method auf O_DIRECT festgelegt haben, obwohl dies unter OS X nicht unterstützt wird.

InnoDB puffert normalerweise Daten und Indizes in 16kb Seiten. Je nachdem, wie Sie den Wert von @eid zwischen Abfragen ändern, hat er möglicherweise bereits die Daten für eine Abfrage zwischengespeichert, da die Datenträger von einer vorherigen Abfrage gelesen wurden.

Stellen Sie sicher, dass Sie die Indizes identisch erstellt haben. Verwenden Sie explain, um zu überprüfen, ob MySQL den Index verwendet. Da Sie die Ausgabe von describe anstelle von show create table oder show indexes von enthalten, kann ich nicht sagen, ob entity_id Teil eines zusammengesetzten Indexes ist. Wenn es nicht der erste Teil eines zusammengesetzten Indexes wäre, würde es nicht verwendet werden.

Wenn Sie eine relativ moderne Version von MySQL verwenden, führen Sie den folgenden Befehl vor dem Ausführen der Abfrage:

Satz Profilierung = 1;

Dadurch wird Abfrage Profiling für Ihre Sitzung aktiviert. Nach dem Ausführen der Abfrage führen Sie

zeigen Sie Profile;

Das zeigt Ihnen die Liste der Abfragen, für die Profile verfügbar sind. Ich denke, dass es standardmäßig die letzten 20 hält. Angenommen, Ihre Abfrage war die erste Abfrage:

Profil für Abfrage 1 anzeigen;

Sie sehen dann die Dauer jeder Phase bei der Ausführung Ihrer Abfrage. Dies ist äußerst nützlich zum Bestimmen, was (z. B. Sperren von Tabellen, Sortieren, Erstellen von temporären Tabellen usw.) eine Abfrage verursacht, die langsam ist.

6

Mein erster Verdacht wäre, dass die ursprüngliche MyISAM-Tabelle und/oder Indizes im Laufe der Zeit fragmentiert wurden, was zu einer langsamen Verschlechterung der Leistung führte. Die InnoDB-Tabelle hat nicht das gleiche Problem, da Sie sie mit allen Daten erstellt haben, die bereits darin enthalten sind (so dass sie alle nacheinander auf der Festplatte gespeichert werden).

Sie könnten diese Theorie testen, indem Sie die MyISAM-Tabelle neu erstellen. Der einfachste Weg, dies zu tun wäre, eine „Null“ verwenden ALTER TABLE-Anweisung:

ALTER TABLE mytable ENGINE = MyISAM; 

Dann die Leistung überprüfen, um zu sehen, ob es besser ist.

Eine andere Möglichkeit wäre, wenn die Datenbank selbst einfach für InnoDB Leistung statt MyISAM abgestimmt ist. InnoDB verwendet z. B. die innodb_buffer_pool_size parameter, um zu ermitteln, wie viel Speicher für die Speicherung zwischengespeicherter Daten und Indizes im Speicher reserviert werden sollte. Aber MyISAM verwendet den Parameter key_buffer. Wenn Ihre Datenbank über einen großen innodb-Pufferpool und einen kleinen Schlüsselpuffer verfügt, ist die InnoDB-Leistung insbesondere bei großen Tabellen besser als die MyISAM-Leistung.

+0

Ein einigermaßen einfacher Test zum Erstellen einer neuen MyISAM -Tabelle und Timing der Abfrage gegen diese Tabelle könnte diese Vermutung bestätigen. –

1

Was sind Ihre Indexdefinitionen? Es gibt Möglichkeiten, wie Sie Indizes für MyISAM erstellen können, in denen Ihre Indexfelder nicht verwendet werden, wenn Sie denken, sie würden dies tun.

Verwandte Themen