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:

-- 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:

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