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

TipoTamaño máximoBytes
TINYBLOB255 bytesL + 1
BLOB65,535 bytes (~64 KB)L + 2
MEDIUMBLOB16,777,215 bytes (~16 MB)L + 3
LONGBLOB4,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ámetro

BLOB vs TEXT

CaracterísticaBLOBTEXT
ContenidoDatos binariosTexto legible
Character setNinguno (bytes crudos)utf8mb4, latin1, etc.
CollationNinguno (binario)Según el character set
ComparacionesByte a byte (case-sensitive)Según collation (normalmente case-insensitive)
DEFAULTNo soportadoNo soportado
ÍndiceSolo prefijoSolo 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_nameValue
max_allowed_packet67108864

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