web-dev-qa-db-fra.com

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

J'ai récemment découvert que MySQL a un moteur de "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 assez 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 au besoin.

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?

30
Michael McGowan

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 en avez plus qu'assez RAM pour toutes les contenir dans RAM à tout moment donné (et "suffisamment de RAM" peut être plus que vous ne le pensez car vous devez prendre en compte tous les autres processus sur la machine, OS IO buffers/cache et ainsi de suite)
  2. Analysez l'intégralité du contenu (toutes les données et 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 tableau suivi de 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.

27
David Spillett

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 grand, 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 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).

15
Morgan Tocker

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 est pas une option pour les "grandes" tables car elle utilise trop de mémoire.

3
magallanes

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.

2
Kondybas

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 verrou 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 plusieurs sessions essaient de créer des tables temporaires Nice MEMORY rapides, le seul thread peut entraîner un sérieux goulot d'étranglement des performances.

1
Eljuan

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.

1
mopsyd

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).

1
user2134886