Ich habe eine MySQL-Tabelle mit über 30 Millionen Datensätzen, die ursprünglich mit myisam gespeichert wurde. Hier ist eine Beschreibung der Tabelle:
Ich würde die folgende Abfrage für diese Tabelle ausführen, die normalerweise etwa 30 Sekunden benötigt. Ich würde @eid jedes Mal ändern, um Datenbank- oder Platten-Caching zu vermeiden.
%Vor%Ich habe diese Tabelle dann in innoDB konvertiert, ohne irgendwelche weiteren Änderungen vorzunehmen, und die gleiche Abfrage kehrt jetzt jedes Mal, wenn ich die Abfrage durchführe, weniger als eine Sekunde zurück. 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 Speicherarten 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 durchführe, sind gegen eine lokale Datenbank, wobei keine anderen Prozesse zum Zeitpunkt der Tests auf die Datenbank treffen.
Das ist ein überraschend großer Leistungsunterschied, aber ich kann mir ein paar Dinge vorstellen, die dazu beitragen könnten.
MyISAM wurde in der Vergangenheit als schneller angesehen als InnoDB, aber für neuere Versionen von InnoDB gilt das für viel kleinere Anwendungsfälle. 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 MySQL-Nutzung.
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 Festplatte zu lesen.
InnoDB speichert beide Indizes und Daten in einem eigenen Speicherpuffer. Sie können das Betriebssystem anweisen, seinen Festplattencache nicht zu verwenden, wenn Sie innodb_flush_method auf O_DIRECT setzen, 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.
Wenn Sie eine relativ moderne Version von MySQL verwenden, führen Sie den folgenden Befehl aus, bevor Sie die Abfrage ausführen:
Profilerstellung = 1;
Dadurch wird die Abfrageprofilerstellung für Ihre Sitzung aktiviert. Führen Sie nach dem Ausführen der Abfrage
auszeige Profile;
Dies 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, führen Sie:
Zeige Profil für Abfrage 1;
Sie sehen dann die Dauer jeder Phase Ihrer Abfrage. Dies ist äußerst nützlich, um zu bestimmen, was (z. B. Tabellensperren, Sortieren, Erstellen von temporären Tabellen usw.) eine langsame Abfrage verursacht.
Das ist ein überraschend großer Leistungsunterschied, aber ich kann mir ein paar Dinge vorstellen, die dazu beitragen könnten.
MyISAM wurde in der Vergangenheit als schneller angesehen als InnoDB, aber für neuere Versionen von InnoDB gilt das für viel kleinere Anwendungsfälle. 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 MySQL-Nutzung.
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 Festplatte zu lesen.
InnoDB speichert beide Indizes und Daten in einem eigenen Speicherpuffer. Sie können das Betriebssystem anweisen, seinen Festplattencache nicht zu verwenden, wenn Sie innodb_flush_method auf O_DIRECT setzen, 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.
Wenn Sie eine relativ moderne Version von MySQL verwenden, führen Sie den folgenden Befehl aus, bevor Sie die Abfrage ausführen:
Profilerstellung = 1;
Dadurch wird die Abfrageprofilerstellung für Ihre Sitzung aktiviert. Führen Sie nach dem Ausführen der Abfrage
auszeige Profile;
Dies 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, führen Sie:
Zeige Profil für Abfrage 1;
Sie sehen dann die Dauer jeder Phase Ihrer Abfrage. Dies ist äußerst nützlich, um zu bestimmen, was (z. B. Tabellensperren, Sortieren, Erstellen von temporären Tabellen usw.) eine langsame Abfrage verursacht.
Ich habe eine MySQL-Tabelle mit über 30 Millionen Datensätzen, die ursprünglich mit myisam gespeichert wurde. Hier ist eine Beschreibung der Tabelle:
Ich würde die folgende Abfrage für diese Tabelle ausführen, die normalerweise etwa 30 Sekunden benötigt. Ich würde @eid jedes Mal ändern, um Datenbank- oder Platten-Caching zu vermeiden.
%Vor%Ich habe diese Tabelle dann in innoDB konvertiert, ohne irgendwelche weiteren Änderungen vorzunehmen, und die gleiche Abfrage kehrt jetzt jedes Mal, wenn ich die Abfrage durchführe, weniger als eine Sekunde zurück. 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 Speicherarten 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 durchführe, sind gegen eine lokale Datenbank, wobei keine anderen Prozesse zum Zeitpunkt der Tests auf die Datenbank treffen.
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.
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.