MEMORY
El motor MEMORY, también conocido como HEAP en versiones antiguas de MySQL, almacena todos los datos de una tabla directamente en la memoria RAM del servidor. No escribe nada en disco, lo que proporciona tiempos de acceso extraordinariamente rápidos tanto para lectura como para escritura. A cambio de esta velocidad, los datos se pierden por completo cuando el servidor MySQL se reinicia, ya sea de forma planificada o por un fallo inesperado.
Este compromiso entre velocidad y volatilidad hace que MEMORY sea ideal para datos temporales que se pueden reconstruir fácilmente: cachés de consultas frecuentes, tablas de búsqueda que se cargan desde otra fuente o almacenamiento intermedio durante procesos de transformación de datos.
Sintaxis
Para crear una tabla MEMORY:
CREATE TABLE nombre_tabla (
columna1 tipo_dato,
columna2 tipo_dato
) ENGINE = MEMORY;Comportamiento básico
Cuando creas una tabla MEMORY, MySQL reserva espacio en la memoria del servidor para almacenar las filas y los índices. No se crea ningún archivo de datos en disco; solo se genera el archivo .frm con la definición de la estructura de la tabla (en versiones anteriores a MySQL 8.0) o se registra en el diccionario de datos del sistema.
CREATE TABLE cache_precios (
producto_id INT PRIMARY KEY,
nombre VARCHAR(100),
precio DECIMAL(10,2),
ultima_actualizacion TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE = MEMORY;Las operaciones en esta tabla son extremadamente rápidas porque no involucran E/S de disco:
INSERT INTO cache_precios (producto_id, nombre, precio)
VALUES (1, 'Laptop Pro 15', 1299.99),
(2, 'Monitor UltraWide', 549.00),
(3, 'Teclado Mecánico', 89.50);
SELECT * FROM cache_precios WHERE producto_id = 2;| producto_id | nombre | precio | ultima_actualizacion |
|---|---|---|---|
| 2 | Monitor UltraWide | 549.00 | 2024-09-15 10:30:00 |
Es fundamental recordar que al reiniciar MySQL, la estructura de la tabla se preserva pero todos los datos desaparecen:
-- Después de reiniciar el servidor
SELECT COUNT(*) FROM cache_precios;| COUNT(*) |
|---|
| 0 |
La tabla existe pero está vacía. Tu aplicación debe estar preparada para reconstruir los datos al detectar que la caché está vacía.
Caso práctico: tipos de índice HASH vs BTREE
Una característica particular del motor MEMORY es que soporta dos tipos de índices con comportamientos muy diferentes. El tipo predeterminado es HASH, que proporciona búsquedas de igualdad extremadamente rápidas pero no soporta búsquedas por rango.
-- Índice HASH (predeterminado): búsquedas de igualdad O(1)
CREATE TABLE sesiones (
session_id VARCHAR(64) PRIMARY KEY,
usuario_id INT NOT NULL,
datos JSON,
INDEX idx_usuario (usuario_id) USING HASH
) ENGINE = MEMORY;Con un índice HASH, las búsquedas exactas son prácticamente instantáneas:
-- Muy rápido: búsqueda de igualdad
SELECT * FROM sesiones WHERE session_id = 'abc123def456';
-- Muy rápido: búsqueda por valor exacto del índice
SELECT * FROM sesiones WHERE usuario_id = 42;Sin embargo, las búsquedas por rango no pueden aprovechar un índice HASH:
-- Lento: escaneo completo de tabla (el índice HASH no sirve para rangos)
SELECT * FROM sesiones WHERE usuario_id > 100;
SELECT * FROM sesiones WHERE usuario_id BETWEEN 50 AND 100;Si necesitas buscar por rangos, crea el índice como BTREE:
CREATE TABLE metricas_temp (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp_ms BIGINT NOT NULL,
valor DECIMAL(10,4),
INDEX idx_tiempo (timestamp_ms) USING BTREE
) ENGINE = MEMORY;Con un índice BTREE, tanto las búsquedas de igualdad como las de rango funcionan eficientemente:
-- Ambas consultas usan el índice BTREE
SELECT * FROM metricas_temp WHERE timestamp_ms = 1694800000000;
SELECT * FROM metricas_temp WHERE timestamp_ms BETWEEN 1694800000000 AND 1694900000000;Caso práctico: límites de tamaño y la variable max_heap_table_size
Las tablas MEMORY están limitadas en tamaño por la variable del sistema max_heap_table_size. Por defecto, este límite es de 16 MB, lo que puede ser insuficiente para cachés de datos grandes.
-- Consultar el límite actual
SELECT @@max_heap_table_size / 1024 / 1024 AS limite_mb;| limite_mb |
|---|
| 16.00 |
Si intentas insertar datos que exceden este límite, MySQL devuelve un error:
-- ERROR 1114 (HY000): The table 'cache_precios' is fullPara aumentar el límite:
-- Cambiar el límite para la sesión actual
SET max_heap_table_size = 256 * 1024 * 1024; -- 256 MB
-- Cambiar el límite global (afecta a nuevas sesiones)
SET GLOBAL max_heap_table_size = 256 * 1024 * 1024;Es importante tener en cuenta que cambiar max_heap_table_size no afecta a las tablas MEMORY que ya existen. Para que el nuevo límite se aplique a una tabla existente, debes recrearla:
ALTER TABLE cache_precios ENGINE = MEMORY;Para una configuración permanente, añade la variable al archivo my.cnf:
[mysqld]
max_heap_table_size = 256M
Recuerda que cada tabla MEMORY consume memoria RAM del servidor. Si creas varias tablas grandes, puedes agotar la memoria disponible y afectar el rendimiento general del servidor, incluyendo el buffer pool de InnoDB.
Caso práctico: tabla de búsqueda para datos frecuentes
Un uso práctico del motor MEMORY es crear tablas de búsqueda que aceleran consultas frecuentes. Por ejemplo, si tu aplicación consulta repetidamente los códigos postales con sus ciudades:
CREATE TABLE lookup_codigos_postales (
codigo_postal VARCHAR(10) PRIMARY KEY,
ciudad VARCHAR(100),
estado VARCHAR(50),
INDEX idx_ciudad (ciudad) USING HASH
) ENGINE = MEMORY;
-- Cargar los datos desde la tabla principal en disco
INSERT INTO lookup_codigos_postales (codigo_postal, ciudad, estado)
SELECT codigo_postal, ciudad, estado
FROM codigos_postales_master;Ahora las búsquedas por código postal son ultrarrápidas:
SELECT ciudad, estado
FROM lookup_codigos_postales
WHERE codigo_postal = '28001';| ciudad | estado |
|---|---|
| Madrid | Comunidad de Madrid |
Para mantener la caché sincronizada, puedes programar una recarga periódica:
TRUNCATE TABLE lookup_codigos_postales;
INSERT INTO lookup_codigos_postales
SELECT codigo_postal, ciudad, estado FROM codigos_postales_master;Limitaciones importantes
El motor MEMORY tiene varias restricciones que debes conocer antes de usarlo. No soporta columnas de tipo TEXT ni BLOB. Si necesitas almacenar texto largo, debes usar VARCHAR con un tamaño máximo definido. Tampoco soporta transacciones, por lo que no puedes usar COMMIT ni ROLLBACK.
Las tablas MEMORY utilizan un formato de fila de longitud fija. Esto significa que una columna VARCHAR(255) siempre ocupa el espacio máximo, independientemente del contenido real. Este comportamiento puede resultar en un consumo de memoria significativamente mayor al esperado.
-- Esta tabla consume mucha más memoria de lo que aparenta
CREATE TABLE ejemplo_memoria (
id INT PRIMARY KEY,
descripcion VARCHAR(500) -- Siempre ocupa 500 caracteres * tamaño del charset
) ENGINE = MEMORY;Advertencia: Nunca almacenes datos críticos exclusivamente en tablas MEMORY. Al reiniciar el servidor, todos los datos se pierden sin posibilidad de recuperación. Usa MEMORY solo como caché o almacenamiento temporal, y asegúrate de que los datos originales existan en una tabla InnoDB u otra fuente persistente.
Consejo: Antes de crear una tabla MEMORY para caché, evalúa si el buffer pool de InnoDB ya cubre tus necesidades. Una tabla InnoDB frecuentemente consultada se almacena automáticamente en el buffer pool, ofreciendo velocidades similares a MEMORY pero con la ventaja de la persistencia.
En el siguiente artículo aprenderás sobre el motor CSV, que almacena los datos en archivos de texto plano con formato CSV.
Escrito por Eduardo Lázaro
