ARCHIVE
El motor ARCHIVE está diseñado para un propósito muy específico: almacenar grandes volúmenes de datos históricos de forma comprimida y eficiente. Su filosofía es simple: los datos se insertan y se consultan, pero nunca se modifican ni se eliminan. Esta restricción permite que ARCHIVE utilice una compresión agresiva con zlib que puede reducir el tamaño de almacenamiento entre un 60% y un 80% comparado con InnoDB o MyISAM.
ARCHIVE es ideal para datos de auditoría, logs de aplicación, registros de transacciones históricas o cualquier conjunto de datos que solo crece y necesita mantenerse disponible para consultas ocasionales sin ocupar espacio excesivo en disco.
Sintaxis
Para crear una tabla con el motor ARCHIVE:
CREATE TABLE nombre_tabla (
columna1 tipo_dato,
columna2 tipo_dato
) ENGINE = ARCHIVE;Comportamiento básico
Cuando creas una tabla ARCHIVE, MySQL genera un archivo con extensión .ARZ que almacena los datos comprimidos. A diferencia de otros motores, ARCHIVE solo permite dos tipos de operaciones DML: INSERT y SELECT. Las sentencias UPDATE y DELETE no están soportadas y producen un error si intentas ejecutarlas.
CREATE TABLE auditoria_login (
id INT AUTO_INCREMENT PRIMARY KEY,
usuario VARCHAR(50) NOT NULL,
ip_origen VARCHAR(45) NOT NULL,
accion VARCHAR(20) NOT NULL,
resultado ENUM('exitoso', 'fallido') NOT NULL,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE = ARCHIVE;La inserción de datos funciona normalmente:
INSERT INTO auditoria_login (usuario, ip_origen, accion, resultado) VALUES
('admin', '192.168.1.10', 'login', 'exitoso'),
('jgarcia', '10.0.1.45', 'login', 'fallido'),
('mlopez', '10.0.1.88', 'login', 'exitoso'),
('admin', '172.16.0.5', 'logout', 'exitoso');Las consultas de lectura también funcionan sin restricciones:
SELECT usuario, ip_origen, resultado, timestamp
FROM auditoria_login
WHERE resultado = 'fallido';| usuario | ip_origen | resultado | timestamp |
|---|---|---|---|
| jgarcia | 10.0.1.45 | fallido | 2024-09-15 14:22:00 |
Pero si intentas modificar o eliminar registros:
UPDATE auditoria_login SET resultado = 'exitoso' WHERE id = 2;
-- ERROR 1031 (HY000): Table storage engine for 'auditoria_login' doesn't have this option
DELETE FROM auditoria_login WHERE id = 2;
-- ERROR 1031 (HY000): Table storage engine for 'auditoria_login' doesn't have this optionEsta limitación es deliberada y, de hecho, es una ventaja para datos de auditoría: garantiza que los registros históricos no pueden ser alterados ni eliminados, proporcionando una pista de auditoría inmutable.
Caso práctico: ahorro de espacio con compresión
Para demostrar la eficiencia de compresión de ARCHIVE, comparemos el tamaño de la misma información almacenada en diferentes motores. Supongamos que tenemos un millón de registros de log:
-- Crear la misma tabla en tres motores diferentes
CREATE TABLE logs_innodb (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME NOT NULL,
nivel VARCHAR(10) NOT NULL,
servicio VARCHAR(50) NOT NULL,
mensaje VARCHAR(500) NOT NULL
) ENGINE = InnoDB;
CREATE TABLE logs_myisam (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME NOT NULL,
nivel VARCHAR(10) NOT NULL,
servicio VARCHAR(50) NOT NULL,
mensaje VARCHAR(500) NOT NULL
) ENGINE = MyISAM;
CREATE TABLE logs_archive (
id INT AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME NOT NULL,
nivel VARCHAR(10) NOT NULL,
servicio VARCHAR(50) NOT NULL,
mensaje VARCHAR(500) NOT NULL
) ENGINE = ARCHIVE;Después de insertar el mismo millón de registros en las tres tablas, podemos comparar el espacio utilizado:
SELECT table_name, engine,
table_rows,
ROUND(data_length / 1024 / 1024, 2) AS datos_mb,
ROUND(index_length / 1024 / 1024, 2) AS indices_mb
FROM information_schema.tables
WHERE table_schema = 'mi_app'
AND table_name LIKE 'logs_%'
ORDER BY data_length;| table_name | engine | table_rows | datos_mb | indices_mb |
|---|---|---|---|---|
| logs_archive | ARCHIVE | 1000000 | 18.50 | 0.00 |
| logs_myisam | MyISAM | 1000000 | 85.30 | 12.40 |
| logs_innodb | InnoDB | 1000000 | 112.00 | 0.00 |
En este ejemplo representativo, ARCHIVE ocupa apenas 18.5 MB frente a los 112 MB de InnoDB, una reducción de más del 80%. Además, ARCHIVE no usa espacio adicional para índices porque no los soporta, salvo la clave primaria AUTO_INCREMENT.
Caso práctico: registro de auditoría de aplicación
Un uso práctico perfecto para ARCHIVE es mantener un registro completo de todas las acciones realizadas en una aplicación, donde la inmutabilidad es una ventaja:
CREATE TABLE audit_trail (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
timestamp DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
usuario VARCHAR(50) NOT NULL,
modulo VARCHAR(50) NOT NULL,
accion VARCHAR(100) NOT NULL,
entidad VARCHAR(50),
entidad_id BIGINT,
datos_anteriores JSON,
datos_nuevos JSON
) ENGINE = ARCHIVE;La aplicación inserta registros cada vez que se realiza una acción relevante:
INSERT INTO audit_trail (usuario, modulo, accion, entidad, entidad_id,
datos_anteriores, datos_nuevos)
VALUES ('carmen.lopez', 'ventas', 'actualizar_precio', 'productos', 1450,
'{"precio": 29.99}', '{"precio": 34.99}');Para consultar el historial de cambios de un registro específico:
SELECT timestamp, usuario, accion, datos_anteriores, datos_nuevos
FROM audit_trail
WHERE entidad = 'productos' AND entidad_id = 1450
ORDER BY timestamp;| timestamp | usuario | accion | datos_anteriores | datos_nuevos |
|---|---|---|---|---|
| 2024-09-10 09:15:30.123 | admin | crear_producto | NULL | {"precio": 24.99} |
| 2024-09-12 14:20:45.456 | juan.martinez | actualizar_precio | {"precio": 24.99} | {"precio": 29.99} |
| 2024-09-15 11:05:12.789 | carmen.lopez | actualizar_precio | {"precio": 29.99} | {"precio": 34.99} |
Dado que ARCHIVE no permite DELETE ni UPDATE, estos registros de auditoría son inmutables por diseño, lo cual es un requisito frecuente en normativas de cumplimiento.
Caso práctico: archivado de datos antiguos
Otra aplicación práctica es mover datos antiguos desde tablas InnoDB activas hacia tablas ARCHIVE para liberar espacio sin perder acceso a la información:
-- Crear la tabla de archivo
CREATE TABLE pedidos_historico (
id INT PRIMARY KEY,
cliente_id INT NOT NULL,
fecha DATETIME NOT NULL,
total DECIMAL(10,2) NOT NULL,
estado VARCHAR(20) NOT NULL
) ENGINE = ARCHIVE;
-- Mover pedidos de más de 2 años a la tabla de archivo
INSERT INTO pedidos_historico
SELECT id, cliente_id, fecha, total, estado
FROM pedidos
WHERE fecha < DATE_SUB(NOW(), INTERVAL 2 YEAR);
-- Eliminar los datos archivados de la tabla principal
DELETE FROM pedidos
WHERE fecha < DATE_SUB(NOW(), INTERVAL 2 YEAR);La tabla pedidos principal queda más ligera y con mejor rendimiento, mientras que los datos históricos siguen disponibles para consultas en pedidos_historico, ocupando una fracción del espacio original.
Advertencia: Las consultas en tablas ARCHIVE que no tengan índice en la columna de filtro siempre realizan un escaneo completo de la tabla. ARCHIVE solo permite índices en la columna
AUTO_INCREMENT. Para tablas muy grandes, las consultas que buscan por otras columnas pueden ser lentas.
Consejo: Si necesitas consultar frecuentemente datos archivados por columnas distintas a la clave primaria, considera crear una tabla InnoDB auxiliar con los campos de búsqueda más comunes y un puntero al ID de la tabla ARCHIVE. Esto te da velocidad de búsqueda con la compresión de ARCHIVE para el almacenamiento principal.
En el siguiente artículo aprenderás sobre el motor BLACKHOLE, que acepta datos sin almacenarlos.
Escrito por Eduardo Lázaro
