Quelles sont les raisons ** PAS ** d'utiliser le moteur de stockage MEMORY dans MySQL?

28

J'ai récemment découvert que MySQL a un moteur "mémoire" que je ne connaissais pas (la plupart de mon travail de base de données est pour des projets de loisir, donc j'apprends ce dont j'ai besoin au fur et à mesure). Il semble que cette option devrait me donner des performances considérablement améliorées, donc je me demande s'il y a des inconvénients qui vont avec. Les deux que je connais sont:

  1. J'ai besoin d'avoir suffisamment de RAM pour contenir la ou les tables en question.
  2. Les tables sont perdues si la machine s'arrête.

Je crois que # 1 ne devrait pas être un problème car j'utilise AWS EC2 et je peux passer à un type d'instance avec plus de mémoire si nécessaire. Je crois que je peux atténuer # 2 en retournant sur le disque si nécessaire.

Quels sont les autres problèmes? Le moteur de mémoire peut-il jamais donner de moins bonnes performances que MyISAM ou InnoDB? Je pense que j'ai lu quelque chose que les indices sont différents avec ce moteur; est-ce quelque chose dont je dois m'inquiéter?

Michael McGowan
la source

Réponses:

27

En regardant la liste de disponibilité des fonctionnalités sur http://dev.mysql.com/doc/refman/5.1/en/memory-storage-engine.html, deux problèmes possibles surgissent:

  1. Aucune transaction ni prise en charge FK, ce qui signifie que vous devrez gérer l'intégrité transactionnelle et l'intégrité référentielle dans votre propre code (ce qui pourrait finir par être beaucoup moins efficace que de laisser la DB le faire pour vous, bien que cela dépende en grande partie de votre application). modèles de comportement attendus).
  2. Verrouillage au niveau de la table uniquement: cela pourrait être un obstacle important à l'évolutivité si votre application a besoin de plusieurs écrivains simultanés pour le même ensemble de tables ou dans les cas où vos opérations de lecture utilisent des verrous pour garantir la lecture de données cohérentes - dans de tels cas, une table sur disque qui prend en charge une granularité de verrouillage beaucoup plus fine fonctionnera beaucoup mieux si suffisamment de son contenu est actuellement mis en cache dans la RAM.

En dehors de cela, en supposant que vous disposez de suffisamment de RAM, une table basée sur la mémoire devrait être plus rapide qu'une table sur disque. De toute évidence, vous devez prendre en compte les instantanés sur le disque pour résoudre le problème de ce qui se passe lorsque l'instance de serveur est réinitialisée, ce qui est susceptible d'annuler complètement les avantages en termes de performances si les données doivent être capturées souvent (si vous pouvez vivre avec perdre une journée de Dans un tel cas, vous pouvez simplement effectuer une sauvegarde une fois par jour, mais dans la plupart des cas, cela ne serait pas acceptable).

Une alternative pourrait être de:

  1. Utilisez des tables basées sur le disque, mais assurez-vous que vous disposez de plus de suffisamment de RAM pour toutes les contenir à tout moment (et "suffisamment de RAM" peut être plus que vous ne le pensez car vous devez tenir compte de tout autre processus sur la machine, OS Tampons IO / cache et ainsi de suite)
  2. Analysez l'intégralité du contenu (toutes les données et les pages d'index) de la table à chaque démarrage pour précharger le contenu en mémoire avec SELECT * FROM <table> ORDER BY <pkey fields>pour chaque table, puis SELECT <indexed fields> FROM <table> ORDER BY <index fields>pour chaque index

De cette façon, toutes vos données sont en RAM, vous n'avez qu'à vous soucier des performances d'E / S pour les opérations d'écriture. Si le jeu de travail commun de votre application est beaucoup plus petit que l'ensemble de la base de données (ce qui est généralement le cas - dans la plupart des applications, la plupart des utilisateurs ne regarderont les données les plus récentes que si le temps le permet), vous pourriez être mieux d'être plus sélectif sur la quantité vous numérisez pour précharger en mémoire, permettant au reste d'être chargé à partir du disque sur demande.

David Spillett
la source
Pourquoi auriez-vous besoin de l'intégrité transactionnelle pour une base de données en mémoire? Si le courant est coupé, vous perdez tout de toute façon.
osa
@osa: en supposant qu'il autorise un accès simultané plutôt que de sérialiser tout, vous allez vouloir une certaine forme de gestion de l'intégrité pour cela.
David Spillett
14

Il existe de nombreux cas pour ne pas utiliser le moteur de stockage de mémoire - et quand InnoDB sera plus rapide. Vous avez juste besoin de penser à la simultanéité et non aux tests simples à un seul thread.

Si vous disposez d'un pool de mémoire tampon suffisamment important, InnoDB deviendra également entièrement résident en mémoire pour les opérations de lecture. Les bases de données ont des caches . Ils se réchauffent!

Aussi - ne sous-estimez pas la valeur du verrouillage au niveau des lignes et du MVCC (les lecteurs ne bloquent pas les écrivains). Il peut être "plus lent" lorsque les écritures doivent persister sur le disque. Mais au moins vous ne bloquerez pas pendant cette opération d'écriture comme vous le feriez sur une table mémoire (pas de MVCC; verrouillage au niveau de la table).

Morgan Tocker
la source
3

Pour mémoire. J'ai testé les tables Mysql en mémoire pour stocker des informations. Et j'ai testé l'APC de PHP (APCu) pour stocker les mêmes informations.

Pour 58000 registres. (varchar + entier + date).

  1. Informations originales 24mb au format texte (format csv).
  2. L'APC de PHP utilise 44,7 Mo de RAM.
  3. La table de Mysql utilise 575 Mo de RAM.

La table n'a qu'un seul index, donc je ne pense pas que ce soit le principal facteur.

Conclusion:

La table mémoire n'est pas une option pour les "grandes" tables car elle utilise trop de mémoire.

magallanes
la source
2
Ceci est une réponse trop simplifiée. Le moteur de stockage MEMORY peut être réglé en utilisant des types de données plus petits, en définissant explicitement BTREE comme type d'index et en limitant la quantité de données chargées dans la RAM. C'est toujours une option viable pour les petits ensembles. Il existe également d'autres facteurs comme les E / S de disque agressives. Voir mes publications dba.stackexchange.com/questions/6156/… et dba.stackexchange.com/questions/2868/… )
RolandoMySQLDBA
En fait, j'ai vérifié en changeant l'index (et même en le supprimant complètement) et la taille n'a pas tellement changé (y compris une reconstruction de la table à partir de zéro). IMHO Mysql fait quelque chose sous le capot, peut être une sorte d'optimisation ou d'allouer la plus grande taille par colonne (comme dans un varchar).
magallanes
6
La raison est presque certainement due à votre 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 En fait, il semblerait que VARCHAR devienne CHAR avec le moteur MEMORY.
Matthew1471
2

L'autre inconvénient des tables basées sur la MÉMOIRE est qu'elles ne peuvent pas être référencées plusieurs fois dans la même requête. Au moins, ce comportement a été constaté jusqu'à la version 5.4. Comment avec les CTE (depuis la v8.x) il n'est pas nécessaire d'utiliser des tables intermédiaires basées sur mem pour les procédures complexes.

Kondybas
la source
1

Selon les manuels MySQL et MariaDB, BLOB et CLOB (divers types TEXT) ne sont pas pris en charge par le stockage MEMORY. Pour nos propres besoins, cela a rendu le moteur de stockage MEMORY presque inutile.

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

Les tables MEMORY ne peuvent pas contenir de colonnes BLOB ou TEXT.

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

Les types de longueur variable comme VARCHAR peuvent être utilisés dans les tables MEMORY. Les colonnes BLOB ou TEXT ne sont pas prises en charge pour les tables MEMORY.

En essayant de convertir seulement une partie de la base de données en stockage MEMORY, j'ai constaté que les clés étrangères du moteur de stockage ne sont pas prises en charge. Ainsi, toutes les tables, qui doivent avoir des références de clé étrangère aux tables, contenant BLOB / CLOB doivent également être dans des types de stockage non-mémoire (au moins, cela affecte les tables enfants InnoDB).

user2134886
la source
1

Les tables MEMORY ne sont pas destinées à un stockage persistant, en particulier de grands sous-ensembles de données ou quoi que ce soit où la rétention est critique. Mon meilleur objectif, d'après mon expérience, est d'héberger des enregistrements transitoires lors de la création et du remplissage de tables temporaires lors de procédures complexes, ce qui est beaucoup plus rapide que la plupart des autres types de tables à cet effet, à condition que votre seuil de tampon clé pour le moteur soit suffisamment élevé pour ne pas subir une écriture sur disque. Cela peut fonctionner à un ordre de grandeur plus rapide que MyISAM ou InnoDB à cet effet car il n'y a pas d'E / S de disque, et dans le cas d'une table qui est encapsulée dans une procédure spécifique, l'indexation et les relations n'ont pas autant d'importance qu'elles serait là où la persistance est attendue.

mopsyd
la source
1

En plus des réponses précédentes. directement à partir du manuel MySQL 5.7:

«Les performances de la MÉMOIRE sont limitées par les conflits résultant de l'exécution d'un seul thread et de la surcharge du verrouillage de table lors du traitement des mises à jour. Cela limite l'évolutivité lorsque la charge augmente, en particulier pour les mélanges d'instructions qui incluent des écritures.»

... et c'est une limitation très réelle. Par exemple: lorsque vous avez plusieurs sessions essayant de créer de belles tables temporaires MEMORY rapides, le seul thread peut provoquer un sérieux goulot d'étranglement des performances.

Eljuan
la source