¿Cuáles son las razones ** NO ** para usar el motor de almacenamiento MEMORY en MySQL?
28
Recientemente descubrí que MySQL tiene un motor de "memoria" del que no estaba al tanto (la mayor parte del trabajo de mi base de datos es para proyectos de hobby, así que aprendo lo que necesito a medida que avanzo). Parece que esta opción debería darme un rendimiento drásticamente mejorado, por lo que me pregunto si hay algún inconveniente que la acompañe. Los dos que conozco son:
Necesito tener suficiente RAM para mantener las tablas en cuestión.
Las tablas se pierden si la máquina se apaga.
Creo que el n. ° 1 no debería ser un problema ya que estoy usando AWS EC2 y puedo pasar a un tipo de instancia con más memoria si es necesario. Creo que puedo mitigar el n. ° 2 volviendo al disco según sea necesario.
¿Qué otros problemas hay? ¿Puede el motor de memoria dar un rendimiento peor que MyISAM o InnoDB? Creo que leí algo que los índices son diferentes con este motor; ¿Es algo de lo que deba preocuparme?
No se necesitan transacciones ni soporte FK, lo que significa que tendrá que administrar la integridad transaccional y la integridad referencial en su propio código (lo que podría terminar siendo mucho menos eficiente que dejar que la base de datos haga esto por usted, aunque eso depende mucho de la aplicación) patrones de comportamiento esperados).
Solo bloqueo de nivel de tabla: esto podría ser una barrera importante para la escalabilidad si su aplicación necesita múltiples escritores concurrentes en el mismo conjunto de tablas o en los casos en que sus operaciones de lectura usan bloqueos para garantizar que se lean datos consistentes, en tales casos una tabla basada en disco que admite una granularidad de bloqueo mucho más fina funcionará mucho mejor si una cantidad suficiente de su contenido se almacena actualmente en la memoria caché
Aparte de eso, suponiendo que tenga suficiente RAM, una tabla basada en memoria debería ser más rápida que una basada en disco. Obviamente, debe tener en cuenta tomar instantáneas en el disco para abordar el problema de lo que sucede cuando se restablece la instancia del servidor, lo que probablemente negará por completo el beneficio de rendimiento en general si los datos necesitan capturarse con frecuencia (si puede vivir con la pérdida de un día de datos en tal caso, podría hacer una copia de seguridad una vez al día, pero en la mayoría de los casos eso no sería aceptable).
Una alternativa podría ser:
Use tablas basadas en disco, pero asegúrese de tener RAM más que suficiente para mantenerlas todas en RAM en cualquier momento dado (y "suficiente RAM" podría ser más de lo que piensa, ya que necesita dar cuenta de cualquier otro proceso en la máquina, SO IO buffers / cache y así sucesivamente)
Escanee todo el contenido (todas las páginas de datos e índices) de la tabla en cada inicio para precargar el contenido en la memoria SELECT * FROM <table> ORDER BY <pkey fields>para cada tabla seguido de SELECT <indexed fields> FROM <table> ORDER BY <index fields>para cada índice
De esta manera, todos sus datos están en RAM, solo tiene que preocuparse por el rendimiento de E / S para las operaciones de escritura. Si el conjunto de trabajo común de su aplicación es mucho más pequeño que toda la base de datos (que suele ser el caso, en la mayoría de las aplicaciones, la mayoría de los usuarios solo mirarán los datos más recientes, si es el momento), podría ser mejor ser más selectivo sobre cuánto escanea para precargar en memoria, permitiendo que el resto se cargue desde el disco a pedido.
¿Por qué necesitaría integridad transaccional para una base de datos en memoria? Si se corta la energía, de todas formas lo está perdiendo todo.
osa
@osa: suponiendo que permite el acceso concurrente en lugar de serializar todo, querrá algún tipo de gestión de integridad para eso.
David Spillett
14
Hay muchos casos para no usar el motor de almacenamiento de memoria, y cuando InnoDB será más rápido. Solo necesita pensar en la concurrencia y no en pruebas triviales de subproceso único.
Si tiene una agrupación de almacenamiento intermedio lo suficientemente grande, InnoDB también se convertirá en residente de memoria para las operaciones de lectura. Las bases de datos tienen cachés . ¡Se calientan!
Además, no subestime el valor del bloqueo de nivel de fila y MVCC (los lectores no bloquean a los escritores). Puede ser "más lento" cuando las escrituras tienen que persistir en el disco. Pero al menos no estará bloqueando durante esa operación de escritura como lo estaría en una tabla de memoria (sin MVCC; bloqueo de nivel de tabla).
Esta es una respuesta demasiado simplificada. El motor de almacenamiento MEMORY se puede ajustar utilizando tipos de datos más pequeños, definiendo explícitamente BTREE como el tipo de índice y limitando la cantidad de datos cargados en la RAM. Sigue siendo una opción viable para conjuntos más pequeños. También hay otros factores como la E / S de disco agresivo. Vea mis publicaciones dba.stackexchange.com/questions/6156/… y dba.stackexchange.com/questions/2868/… )
RolandoMySQLDBA
De hecho, verifiqué cambiar el índice (e incluso eliminarlo por completo) y el tamaño no cambió mucho (incluida una reconstrucción de la tabla desde cero). En mi humilde opinión, Mysql está haciendo algo bajo el capó, puede ser algún tipo de optimización o asignar el mayor tamaño por columna (como en un varchar).
magallanes
66
El motivo casi seguro se debe a su 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 Efectivamente, parece que VARCHAR se convierte en CHAR con el motor MEMORY.
Matthew1471
2
La otra desventaja de las tablas basadas en MEMORIA es que no se pueden referir varias veces en la misma consulta. Al menos ese comportamiento se encontró hasta la v5.4. Cómo con los CTE (desde v8.x) no hay necesidad de usar tablas intermedias basadas en mem para procedimientos complejos.
De acuerdo con los manuales de MySQL y MariaDB, el almacenamiento de MEMORIA no admite BLOB y CLOB (varios tipos de TEXTO). Para nuestros propios fines, esto hizo que el motor de almacenamiento MEMORY fuera casi inútil.
Los tipos de longitud variable como VARCHAR se pueden usar en las tablas de MEMORIA. Las columnas BLOB o TEXT no son compatibles con las tablas MEMORY.
Al intentar convertir solo una parte de la base de datos en almacenamiento de MEMORIA, descubrí que las claves externas del motor de almacenamiento intermedio no son compatibles. Por lo tanto, todas las tablas, que deben tener referencias de clave externa a las tablas, que contengan BLOB / CLOB también deben estar en tipos de almacenamiento sin memoria (al menos, esto afecta las tablas secundarias de InnoDB).
Las tablas de MEMORIA no están destinadas al almacenamiento persistente, particularmente de grandes subconjuntos de datos o cualquier cosa donde la retención sea crítica. El mejor propósito de mi experiencia es alojar registros transitorios durante la creación y la población de tablas temporales durante procedimientos complejos, que se desempeña significativamente más rápido que la mayoría de los otros tipos de tablas para este propósito, siempre que el umbral de la memoria intermedia clave para el motor esté lo suficientemente alto como para no incurrir Un disco de escritura. Esto puede funcionar en un orden de magnitud más rápido que MyISAM o InnoDB para este propósito, ya que no hay E / S de disco, y en el caso de una tabla que está encapsulada dentro de un procedimiento específico, la indexación y las relaciones no tienen tanta importancia como sería donde se espera persistencia.
Además de las respuestas anteriores. directamente del manual de MySQL 5.7:
"El rendimiento de la MEMORIA está limitado por la contención que resulta de la ejecución de un solo subproceso y la sobrecarga de bloqueo de la tabla al procesar actualizaciones. Esto limita la escalabilidad cuando aumenta la carga, particularmente para las mezclas de instrucciones que incluyen escrituras".
... y esta es una limitación muy real. Por ejemplo: cuando tiene varias sesiones tratando de crear tablas temporales MEMORY rápidas y agradables, el subproceso único puede causar un serio cuello de botella en el rendimiento.
Hay muchos casos para no usar el motor de almacenamiento de memoria, y cuando InnoDB será más rápido. Solo necesita pensar en la concurrencia y no en pruebas triviales de subproceso único.
Si tiene una agrupación de almacenamiento intermedio lo suficientemente grande, InnoDB también se convertirá en residente de memoria para las operaciones de lectura. Las bases de datos tienen cachés . ¡Se calientan!
Además, no subestime el valor del bloqueo de nivel de fila y MVCC (los lectores no bloquean a los escritores). Puede ser "más lento" cuando las escrituras tienen que persistir en el disco. Pero al menos no estará bloqueando durante esa operación de escritura como lo estaría en una tabla de memoria (sin MVCC; bloqueo de nivel de tabla).
fuente
Para el registro. Probé tablas Mysql en la memoria para almacenar información. Y probé el APC de PHP (APCu) para almacenar la misma información.
Para 58000 registros. (varchar + entero + fecha).
La tabla solo tiene un índice único, así que no creo que sea el factor principal.
Conclusión:
La tabla de memoria no es una opción para tablas "grandes" porque usa demasiada memoria.
fuente
"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 Efectivamente, parece que VARCHAR se convierte en CHAR con el motor MEMORY.La otra desventaja de las tablas basadas en MEMORIA es que no se pueden referir varias veces en la misma consulta. Al menos ese comportamiento se encontró hasta la v5.4. Cómo con los CTE (desde v8.x) no hay necesidad de usar tablas intermedias basadas en mem para procedimientos complejos.
fuente
De acuerdo con los manuales de MySQL y MariaDB, el almacenamiento de MEMORIA no admite BLOB y CLOB (varios tipos de TEXTO). Para nuestros propios fines, esto hizo que el motor de almacenamiento MEMORY fuera casi inútil.
http://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html
https://mariadb.com/kb/en/mariadb/memory-storage-engine/
Al intentar convertir solo una parte de la base de datos en almacenamiento de MEMORIA, descubrí que las claves externas del motor de almacenamiento intermedio no son compatibles. Por lo tanto, todas las tablas, que deben tener referencias de clave externa a las tablas, que contengan BLOB / CLOB también deben estar en tipos de almacenamiento sin memoria (al menos, esto afecta las tablas secundarias de InnoDB).
fuente
Las tablas de MEMORIA no están destinadas al almacenamiento persistente, particularmente de grandes subconjuntos de datos o cualquier cosa donde la retención sea crítica. El mejor propósito de mi experiencia es alojar registros transitorios durante la creación y la población de tablas temporales durante procedimientos complejos, que se desempeña significativamente más rápido que la mayoría de los otros tipos de tablas para este propósito, siempre que el umbral de la memoria intermedia clave para el motor esté lo suficientemente alto como para no incurrir Un disco de escritura. Esto puede funcionar en un orden de magnitud más rápido que MyISAM o InnoDB para este propósito, ya que no hay E / S de disco, y en el caso de una tabla que está encapsulada dentro de un procedimiento específico, la indexación y las relaciones no tienen tanta importancia como sería donde se espera persistencia.
fuente
Además de las respuestas anteriores. directamente del manual de MySQL 5.7:
"El rendimiento de la MEMORIA está limitado por la contención que resulta de la ejecución de un solo subproceso y la sobrecarga de bloqueo de la tabla al procesar actualizaciones. Esto limita la escalabilidad cuando aumenta la carga, particularmente para las mezclas de instrucciones que incluyen escrituras".
... y esta es una limitación muy real. Por ejemplo: cuando tiene varias sesiones tratando de crear tablas temporales MEMORY rápidas y agradables, el subproceso único puede causar un serio cuello de botella en el rendimiento.
fuente