Was sind die Gründe, warum ** NICHT ** die MEMORY-Speicher-Engine in MySQL verwendet wird?

28

Ich habe kürzlich entdeckt, dass MySQL eine "Speicher" -Engine hat, die mir nicht bekannt war (der Großteil meiner Datenbankarbeit ist für Hobbyprojekte bestimmt, also lerne ich, was ich brauche, wenn ich gehe). Anscheinend sollte diese Option zu einer drastisch verbesserten Leistung führen. Ich frage mich daher, ob dies mit Nachteilen verbunden ist. Die beiden, die ich kenne, sind:

  1. Ich muss über genügend RAM verfügen, um die fraglichen Tische aufnehmen zu können.
  2. Die Tabellen gehen verloren, wenn die Maschine herunterfährt.

Ich glaube, # 1 sollte kein Problem sein, da ich AWS EC2 verwende und bei Bedarf auf einen Instanztyp mit mehr Arbeitsspeicher umsteigen kann. Ich glaube, ich kann # 2 lindern, indem ich nach Bedarf auf die Festplatte zurückspeichere.

Welche anderen Probleme gibt es? Kann die Speicher-Engine jemals eine schlechtere Leistung liefern als MyISAM oder InnoDB? Ich glaube, ich habe etwas gelesen, bei dem die Indizes bei dieser Engine anders sind. Muss ich mir darüber Sorgen machen?

Michael McGowan
quelle

Antworten:

27

In der Liste der verfügbaren Funktionen unter http://dev.mysql.com/doc/refman/5.1/en/memory-storage-engine.html sind zwei mögliche Probleme aufgeführt:

  1. Keine Transaktions- oder FK-Unterstützung, das heißt, Sie müssen die Transaktionsintegrität und die referenzielle Integrität in Ihrem eigenen Code verwalten (was möglicherweise weniger effizient ist, als wenn die DB dies für Sie tun würde, obwohl dies sehr stark von Ihrer App abhängt erwartete Verhaltensmuster).
  2. Nur Sperren auf Tabellenebene: Dies kann ein erhebliches Hindernis für die Skalierbarkeit sein, wenn Ihre App mehrere gleichzeitige Writer für dieselbe Gruppe von Tabellen benötigt oder wenn Ihre Lesevorgänge Sperren verwenden, um sicherzustellen, dass konsistente Daten gelesen werden - in solchen Fällen eine festplattenbasierte Tabelle, die Unterstützt viel feinere Sperrgranularität wird weitaus besser ausgeführt, wenn genügend Inhalt derzeit im RAM zwischengespeichert ist.

Ansonsten sollte eine speicherbasierte Tabelle schneller sein als eine festplattenbasierte, vorausgesetzt, Sie haben genügend RAM. Offensichtlich müssen Sie die Erstellung von Snapshots auf der Festplatte berücksichtigen, um das Problem zu beheben, das beim Zurücksetzen der Serverinstanz auftritt. Dies kann den Leistungsvorteil insgesamt beeinträchtigen, wenn die Daten häufig erfasst werden müssen (wenn Sie einen Tag Zeit verlieren) Daten in einem solchen Fall könnten Sie nur einmal pro Tag eine Sicherungskopie erstellen, aber in den meisten Fällen wäre dies nicht akzeptabel.

Eine Alternative könnte sein:

  1. Verwenden Sie festplattenbasierte Tabellen, aber stellen Sie sicher, dass Sie über mehr als genug RAM verfügen, um sie alle zu einem bestimmten Zeitpunkt im RAM zu halten (und "genug RAM" ist möglicherweise mehr als Sie denken, da Sie andere Prozesse auf dem Computer, Betriebssystem, berücksichtigen müssen IO-Puffer / Cache usw.)
  2. Scannen Sie bei jedem Start den gesamten Inhalt (alle Daten- und Indexseiten) der Tabelle, um den Inhalt mit in den Speicher zu laden SELECT * FROM <table> ORDER BY <pkey fields> für jede Tabelle gefolgt von SELECT <indexed fields> FROM <table> ORDER BY <index fields>jedem Index

Auf diese Weise befinden sich alle Ihre Daten im RAM. Sie müssen sich nur um die E / A-Leistung für Schreibvorgänge kümmern. Wenn der gemeinsame Arbeitssatz Ihrer App viel kleiner ist als die gesamte Datenbank (was in der Regel der Fall ist - in den meisten Anwendungen werden die meisten Benutzer zu gegebener Zeit nur die neuesten Daten betrachten), ist es möglicherweise besser, die Auswahl zu treffen Sie scannen, um vorab in den Speicher zu laden, sodass der Rest bei Bedarf von der Festplatte geladen werden kann.

David Spillett
quelle
Warum benötigen Sie Transaktionsintegrität für eine In-Memory-Datenbank? Wenn der Strom ausfällt, verlieren Sie sowieso alles.
osa
@osa: Angenommen, es erlaubt den gleichzeitigen Zugriff, anstatt alles zu serialisieren, möchten Sie dafür eine Art Integritätsmanagement.
David Spillett
14

Es gibt viele Fälle, in denen die Speicher-Engine nicht verwendet wird - und in denen InnoDB schneller ist. Sie müssen nur über Parallelitätstests nachdenken und nicht über triviale Einzelthread-Tests.

Wenn Sie über einen ausreichend großen Pufferpool verfügen, wird InnoDB auch für Leseoperationen vollständig speicherresident. Datenbanken haben Caches . Sie wärmen sich auf!

Unterschätzen Sie auch nicht den Wert von Sperren auf Zeilenebene und MVCC (Leser blockieren keine Schreiber). Es kann "langsamer" sein, wenn Schreibvorgänge auf der Festplatte bestehen bleiben müssen. Aber zumindest werden Sie während dieser Schreiboperation nicht blockieren, wie Sie es bei einer Speichertabelle tun würden (kein MVCC; Sperren auf Tabellenebene).

Morgan Tocker
quelle
3

Für die Aufzeichnung. Ich habe Mysql-Tabellen im Speicher getestet, um einige Informationen zu speichern. Und ich habe PHPs APC (APCu) getestet, um die gleichen Informationen zu speichern.

Für 58000 Registrierungen. (varchar + integer + date).

  1. Originalinformationen 24 MB im Textformat (CSV-Format).
  2. Der APC von PHP verwendet 44,7 MB RAM.
  3. MySQL-Tabelle verwendet 575 MB RAM.

Die Tabelle hat nur einen einzigen Index, daher denke ich nicht, dass dies der Hauptfaktor ist.

Fazit:

Speichertabelle ist keine Option für "große" Tabellen, da zu viel Speicher verwendet wird.

Magallane
quelle
2
Dies ist eine vereinfachte Antwort. Die MEMORY-Speicher-Engine kann mithilfe kleinerer Datentypen optimiert werden, indem BTREE explizit als Indextyp definiert und die in den RAM geladene Datenmenge begrenzt wird. Es ist immer noch eine praktikable Option für kleinere Sets. Es gibt auch andere Faktoren wie aggressive Festplatten-E / A. Siehe meine Beiträge dba.stackexchange.com/questions/6156/… und dba.stackexchange.com/questions/2868/… )
RolandoMySQLDBA
Tatsächlich überprüfte ich das Ändern des Indexes (und löschte ihn sogar vollständig) und die Größe änderte sich nicht so sehr (einschließlich einer Rekonstruktion der Tabelle von Grund auf neu). IMHO Mysql tut etwas unter der Haube, kann eine Art Optimierung sein oder die größte Größe pro Spalte zuweisen (wie in einem Varchar).
Magallanes
6
Der Grund liegt mit ziemlicher Sicherheit an Ihrem VARCHAR: "MEMORY tables use a fixed-length row-storage format. Variable-length types such as VARCHAR are stored using a fixed length." dev.mysql.com/doc/refman/5.6/en/memory-storage-engine.html Es scheint, als würde VARCHAR mit der MEMORY-Engine zu CHAR.
Matthew1471
2

Der andere Nachteil der MEMORY-basierten Tabellen besteht darin, dass sie nicht mehrmals in derselben Abfrage referenziert werden können. Zumindest wurde dieses Verhalten bis zur v5.4 gefunden. Wie bei CTEs (seit v8.x) ist es nicht erforderlich, mem-basierte Zwischentabellen für komplexe Prozeduren zu verwenden.

Kondybas
quelle
1

Gemäß den MySQL- und MariaDB-Handbüchern werden BLOB und CLOB (verschiedene TEXT-Typen) vom MEMORY-Speicher nicht unterstützt. Für unsere eigenen Zwecke machte dies die Speicher-Engine MEMORY fast unbrauchbar.

http://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html

MEMORY-Tabellen dürfen keine BLOB- oder TEXT-Spalten enthalten.

https://mariadb.com/kb/en/mariadb/memory-storage-engine/

Typen mit variabler Länge wie VARCHAR können in MEMORY-Tabellen verwendet werden. BLOB- oder TEXT-Spalten werden für MEMORY-Tabellen nicht unterstützt.

Bei dem Versuch, nur einen Teil der Datenbank in den MEMORY-Speicher zu konvertieren, wurde festgestellt, dass Fremdschlüssel zwischen den Speichermodulen nicht unterstützt werden. Alle Tabellen, die Fremdschlüsselverweise auf die Tabellen mit BLOB / CLOB enthalten sollten, sollten sich also auch in Speichertypen ohne Arbeitsspeicher befinden (zumindest betrifft dies InnoDB-untergeordnete Tabellen).

user2134886
quelle
1

MEMORY-Tabellen sind nicht für die dauerhafte Speicherung gedacht, insbesondere nicht für große Datenmengen oder alles, wo die Aufbewahrung kritisch ist. Meiner Erfahrung nach besteht der beste Zweck darin, vorübergehende Datensätze während der Erstellung und Auffüllung temporärer Tabellen während komplexer Prozeduren zu speichern. Dies ist erheblich schneller als bei den meisten anderen Tabellentypen für diesen Zweck, vorausgesetzt, Ihr Schlüsselpufferschwellenwert für die Engine ist hoch genug, um nicht aufzutreten eine Festplatte schreiben. Dies kann zu diesem Zweck eine Größenordnung schneller als MyISAM oder InnoDB ausgeführt werden, da keine Platten-E / A vorhanden sind. Bei einer Tabelle, die in einer bestimmten Prozedur eingekapselt ist, sind Indexierung und Relationen weniger wichtig als sie würde wo Ausdauer erwartet wird.

Mopsyd
quelle
1

Zusätzlich zu den vorherigen Antworten. direkt aus dem MySQL 5.7 Handbuch:

"Die Leistung von MEMORY wird durch Konflikte eingeschränkt, die sich aus der Ausführung eines einzelnen Threads und dem Overhead der Tabellensperre bei der Verarbeitung von Aktualisierungen ergeben. Dies schränkt die Skalierbarkeit ein, wenn die Auslastung zunimmt, insbesondere bei Anweisungsmischungen, die Schreibvorgänge enthalten."

... und das ist eine sehr reale Einschränkung. Beispiel: Wenn Sie in mehreren Sitzungen versuchen, schöne, schnelle temporäre MEMORY-Tabellen zu erstellen, kann das Single-Threading einen schwerwiegenden Leistungsengpass verursachen.

Eljuan
quelle