BLOB
Los tipos BLOB (Binary Large Object) almacenan datos binarios sin interpretar: imágenes, PDFs, archivos comprimidos, datos serializados o cualquier secuencia de bytes. A diferencia de TEXT, BLOB no tiene conjunto de caracteres ni collation. Las comparaciones y ordenamientos se hacen byte a byte.
Los cuatro tipos BLOB
| Tipo | Tamaño máximo | Bytes |
|---|---|---|
| TINYBLOB | 255 bytes | L + 1 |
| BLOB | 65,535 bytes (~64 KB) | L + 2 |
| MEDIUMBLOB | 16,777,215 bytes (~16 MB) | L + 3 |
| LONGBLOB | 4,294,967,295 bytes (~4 GB) | L + 4 |
L es la longitud real de los datos. El prefijo (1-4 bytes) almacena la longitud.
Ejemplo básico
CREATE TABLE archivos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(255) NOT NULL,
tipo_mime VARCHAR(100) NOT NULL,
tamano INT UNSIGNED NOT NULL,
contenido MEDIUMBLOB NOT NULL,
subido_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Insertar datos binarios desde un archivo (desde el cliente MySQL)
-- LOAD_FILE lee un archivo del sistema de archivos del servidor
INSERT INTO archivos (nombre, tipo_mime, tamano, contenido)
VALUES ('logo.png', 'image/png', 4096, LOAD_FILE('/ruta/al/logo.png'));En la práctica, la inserción de datos binarios se hace desde una aplicación:
-- Desde una aplicación, se usaría un prepared statement
-- INSERT INTO archivos (nombre, tipo_mime, tamano, contenido) VALUES (?, ?, ?, ?)
-- Y se pasaría el contenido binario como parámetroBLOB vs TEXT
| Característica | BLOB | TEXT |
|---|---|---|
| Contenido | Datos binarios | Texto legible |
| Character set | Ninguno (bytes crudos) | utf8mb4, latin1, etc. |
| Collation | Ninguno (binario) | Según el character set |
| Comparaciones | Byte a byte (case-sensitive) | Según collation (normalmente case-insensitive) |
| DEFAULT | No soportado | No soportado |
| Índice | Solo prefijo | Solo prefijo |
Almacenar imágenes
CREATE TABLE avatares (
usuario_id INT PRIMARY KEY,
imagen BLOB NOT NULL,
formato ENUM('jpeg', 'png', 'webp') NOT NULL,
FOREIGN KEY (usuario_id) REFERENCES clientes(id)
);Aunque es posible almacenar imágenes en MySQL, en la mayoría de los casos es mejor almacenar el archivo en el sistema de archivos o en un servicio de almacenamiento (S3, Cloud Storage) y guardar solo la ruta en la base de datos. En este caso, una columna VARCHAR para la ruta es la elección habitual:
-- Mejor enfoque: guardar la ruta, no el archivo
CREATE TABLE avatares_ref (
usuario_id INT PRIMARY KEY,
ruta_imagen VARCHAR(500) NOT NULL,
formato ENUM('jpeg', 'png', 'webp') NOT NULL,
FOREIGN KEY (usuario_id) REFERENCES clientes(id)
);Cuándo usar BLOB
Sí usar BLOB:
- Datos pequeños que necesitan integridad transaccional (firmas digitales, tokens encriptados)
- Prototipos rápidos donde la infraestructura de archivos no está lista
- Datos binarios que deben viajar con el backup de la base de datos
- Thumbnails o imágenes muy pequeñas (menos de 10 KB)
No usar BLOB:
- Imágenes, videos o archivos grandes (usar sistema de archivos o almacenamiento en la nube)
- Datos que necesitan ser servidos directamente por un servidor web
- Archivos que se acceden con frecuencia (cada lectura carga la base de datos)
Funciones con BLOB
-- LENGTH devuelve el tamaño en bytes
SELECT nombre, LENGTH(contenido) AS bytes FROM archivos;
-- HEX convierte a representación hexadecimal
SELECT HEX(contenido) AS hex_contenido FROM archivos LIMIT 1;
-- Crear datos binarios desde hexadecimal
SELECT UNHEX('48656C6C6F') AS binario;| binario |
|---|
| Hello |
Almacenar datos encriptados
Un caso de uso legítimo para BLOB es almacenar datos encriptados. Para datos binarios de longitud variable pero más pequeños, considera el tipo VARBINARY. Para texto largo sin datos binarios, el tipo TEXT es la alternativa adecuada:
CREATE TABLE datos_sensibles (
id INT AUTO_INCREMENT PRIMARY KEY,
usuario_id INT NOT NULL,
dato_encriptado BLOB NOT NULL,
iv BINARY(16) NOT NULL,
creado_en TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- AES_ENCRYPT y AES_DECRYPT de MySQL
INSERT INTO datos_sensibles (usuario_id, dato_encriptado, iv)
VALUES (1, AES_ENCRYPT('datos secretos', 'clave_secreta'), RANDOM_BYTES(16));Limitaciones
Sin DEFAULT: Al igual que TEXT, las columnas BLOB no pueden tener un valor por defecto.
Índices de prefijo: Solo puedes indexar los primeros N bytes:
CREATE TABLE docs (
id INT PRIMARY KEY,
contenido BLOB,
INDEX idx_contenido (contenido(100))
);max_allowed_packet: El tamaño máximo de un paquete MySQL limita el tamaño del BLOB que puedes insertar. El valor por defecto es 64 MB:
SHOW VARIABLES LIKE 'max_allowed_packet';| Variable_name | Value |
|---|---|
| max_allowed_packet | 67108864 |
Para insertar BLOBs más grandes, necesitas aumentar este valor en la configuración del servidor.
Limpieza
DROP TABLE IF EXISTS archivos;
DROP TABLE IF EXISTS avatares;
DROP TABLE IF EXISTS avatares_ref;
DROP TABLE IF EXISTS datos_sensibles;
DROP TABLE IF EXISTS docs;En el siguiente artículo veremos VARBINARY y BINARY, los tipos binarios de longitud fija y variable para datos más pequeños.
Escrito por Eduardo Lázaro
