Cómo elegir el tipo numérico correcto en SQL — Diferencias entre INT, BIGINT, DECIMAL y FLOAT [Guía de diseño de BD]

Cuando diseñas una tabla en tu base de datos, ¿cómo decides qué tipo numérico asignarle a cada columna?

«Para enteros, INT y listo.» «Mejor prevenir que curar: ponle BIGINT.» «Tiene decimales, así que FLOAT.» Si estas frases te resultan familiares, no eres el único. Pero tomar decisiones por defecto así puede provocar problemas de rendimiento, desperdicio de almacenamiento e incluso errores críticos en cálculos financieros a medio plazo.

Piensa en esto: cambiar INT por BIGINT en una sola columna de una tabla con 100 millones de filas añade aproximadamente 400 MB de almacenamiento. Si sumamos dos índices, la diferencia supera 1 GB. En el extremo opuesto, elegir INT para una tabla de logs de alto volumen que crece millones de filas al día puede provocar un desbordamiento en pocos años, deteniendo tu aplicación por completo.

Y luego está FLOAT. La mayoría de los desarrolladores saben que 0.1 + 0.2 da como resultado 0.30000000000000004 en lugar de 0.3. Sin embargo, las columnas FLOAT siguen apareciendo en tablas de pagos en producción, acumulando silenciosamente errores de redondeo hasta que los informes de facturación mensual dejan de cuadrar.

Este artículo es una guía completa de los cuatro tipos numéricos más importantes en SQL — INT, BIGINT, DECIMAL y FLOAT — cubriendo sus diferencias, ventajas y desventajas, y reglas prácticas de decisión que puedes aplicar de inmediato.

💡 Tip

El diseño de base de datos es la base de cualquier sistema de software. Para fundamentos de diseño orientado a objetos, consulta la Guía de Principios SOLID. Si necesitas ayuda para elegir un lenguaje de programación, echa un vistazo a la Guía Comparativa de Lenguajes de Programación.

Tipos numéricos en SQL de un vistazo

Empecemos con la visión general. La siguiente tabla resume todos los tipos numéricos principales. En las secciones siguientes profundizaremos en cada uno.

TipoTamañoRango (aprox.)PrecisiónUso típico
TINYINT1 byte0 – 255 / -128 – 127ExactaFlags, códigos de estado
SMALLINT2 bytes0 – 65.535ExactaContadores pequeños
INT4 bytes~2.100 millones / ~4.200 millonesExactaIDs, cantidades, contadores
BIGINT8 bytes~9,2 trillonesExactaIDs de log, PKs a gran escala
DECIMAL(M,D)VariableM dígitos (D decimales)ExactaDinero, tasas de impuestos, ratios
FLOAT4 bytes±3,4 × 10³⁸AproximadaTemperatura, datos de sensores
DOUBLE8 bytes±1,7 × 10³⁰⁸AproximadaCoordenadas GPS, estadísticas

Los cuatro tipos que más importan en el día a día son INT, BIGINT, DECIMAL y FLOAT. Domina estos cuatro y podrás resolver la gran mayoría de diseños de bases de datos del mundo real sin problemas.

Tipos enteros (familia INT) — El punto de partida por defecto

Los enteros son el tipo numérico más rápido, más eficiente en almacenamiento y libre de errores en SQL. Ganan en velocidad de cálculo, eficiencia de índices y huella en disco. Si una columna no necesita decimales, un tipo entero es siempre la elección correcta.

MySQL ofrece cinco tamaños de enteros:

TipoTamañoRango SIGNEDRango UNSIGNED
TINYINT1 byte-128 a 1270 a 255
SMALLINT2 bytes-32.768 a 32.7670 a 65.535
MEDIUMINT3 bytes-8.388.608 a 8.388.6070 a 16.777.215
INT4 bytes-2.147.483.648 a 2.147.483.6470 a 4.294.967.295
BIGINT8 bytes-9,2 trillones a 9,2 trillones0 a ~18,4 trillones

La regla de oro: si puedes representarlo como un entero, usa un tipo entero. Por ejemplo, si tu sistema maneja precios en céntimos de euro, price_cents INT funciona perfectamente. INT llega hasta unos 2.100 millones, lo que significa que puede manejar cantidades de hasta 21 millones de euros en céntimos — más que suficiente para la mayoría de productos de e-commerce.

Casos de uso habituales para enteros:

  • IDs (claves primarias): user_id, product_id, order_id
  • Cantidades: stock_quantity, cart_count
  • Contadores: login_count, view_count, retry_count
  • Códigos de estado: order_status (0 = pendiente, 1 = pagado, 2 = enviado …)
  • Flags booleanos: is_active, is_deleted (TINYINT con 0/1)

No hay ninguna razón para usar DECIMAL o FLOAT en estos casos. Los enteros son la opción más rápida y segura.

INT vs. BIGINT — ¿«Mejor prevenir que curar» es realmente seguro?

El dilema más frecuente al elegir un tipo entero es INT frente a BIGINT. La respuesta corta: INT es suficiente para la inmensa mayoría de los casos de uso. La respuesta larga revela por qué ascender todo a BIGINT a ciegas es un antipatrón costoso.

Primero, pongamos las cifras en perspectiva. INT UNSIGNED llega hasta unos 4.200 millones. La población de España es de unos 47 millones — apenas un 1,1 % de la capacidad de INT. Un servicio web con 1 millón de usuarios podría almacenar 4.000 registros de log por usuario y seguir dentro del rango de INT. Para IDs de usuario, de producto y de pedido, INT es casi siempre más que suficiente.

Entonces, ¿cuándo se hace necesario BIGINT?

  • Logs de acceso: Un sitio con 100 millones de páginas vistas al mes acumula 1.200 millones de filas al año. En 3–4 años, el techo de INT está a la vista
  • Datos de sensores IoT: 10.000 dispositivos enviando datos cada segundo generan aproximadamente 315.000 millones de filas al año — muy por encima del rango de INT
  • IDs distribuidos (Snowflake, etc.): Codifican un timestamp, un ID de worker y un número de secuencia en un solo valor que puede ser extremadamente grande
  • IDs de transacciones: Un sistema de pagos que procesa 1 millón de transacciones al día alcanza 3.650 millones en 10 años — peligrosamente cerca del límite de INT

Ahora cuantifiquemos el coste de «usar BIGINT para todo»:

EscenarioINT (4 bytes)BIGINT (8 bytes)Diferencia
100M filas × 1 columna381 MB762 MB+381 MB
100M filas × 1 col + 2 índices1,14 GB2,29 GB+1,14 GB
Memoria para JOIN (estimada)Línea base~1,5–2×Menor eficiencia de caché

En una tabla de 100 millones de filas, cambiar una sola columna más dos índices de INT a BIGINT desperdicia más de 1,1 GB. Multiplica eso por varias columnas y varias tablas, y el total puede alcanzar decenas de gigabytes — todo lo cual incrementa la E/S de disco, reduce la eficiencia del buffer pool y ralentiza las consultas.

Una guía práctica de decisión:

Propósito de la columnaTipo recomendadoRazonamiento
ID de usuarioINT UNSIGNEDMuy pocos servicios superan los 4.200 millones de usuarios
ID de productoINT UNSIGNEDMismo razonamiento
ID de pedidoINT UNSIGNED o BIGINTDepende del volumen y la vida útil
ID de log de accesoBIGINTMiles de millones de filas esperadas al año
Snowflake / UUID numéricoBIGINTLos valores son inherentemente grandes
⚠️ Error común

No bases tu elección solo en el número actual de filas. Lo que importa es la tasa de crecimiento durante toda la vida operativa del sistema. Estima las inserciones anuales, proyéctalas a 10 años y comprueba si INT UNSIGNED (4.200 millones) aguantará. Si no, empieza con BIGINT desde el primer día.

UNSIGNED — El doble de rango gratis

En MySQL y MariaDB, añadir UNSIGNED a una columna entera elimina el rango negativo y duplica el rango positivo sin coste adicional de almacenamiento. Un INT normal abarca desde aproximadamente -2.100 millones hasta +2.100 millones; INT UNSIGNED abarca 0 a 4.200 millones — los mismos 4 bytes.

Columnas como IDs, cantidades y contadores nunca son negativas. No hay razón para no usar UNSIGNED en ellas.

Ejemplo de uso de UNSIGNED
CREATE TABLE users (n  id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,n  age         TINYINT UNSIGNED,          u002du002d 0u0026lt;=255 es suficienten  login_count INT UNSIGNED DEFAULT 0,n  point       INT UNSIGNED DEFAULT 0n);
⚠️ Error común

La resta entre dos columnas UNSIGNED puede provocar un underflow. En MySQL, SELECT a - b donde a < b produce un valor enorme (o un error) porque el resultado «da la vuelta». Si la resta es posible, usa CAST(a AS SIGNED) - CAST(b AS SIGNED) o considera mantener la columna como SIGNED.

Nota: PostgreSQL no soporta UNSIGNED. La solución habitual es usar una restricción CHECK (CHECK (id >= 0)) para forzar valores no negativos a nivel de aplicación.

DECIMAL (NUMERIC) — La única opción correcta para dinero

DECIMAL almacena números como valores exactos en base 10. A diferencia de FLOAT, no convierte internamente a binario, por lo que 0,1 se almacena exactamente como 0,1. Para cualquier columna donde importe hasta la última fracción de céntimo — precios, facturas, impuestos, saldos de cuentas — DECIMAL es el único tipo aceptable.

¿Por qué no FLOAT? Veamos el problema en acción:

Comparación de precisión FLOAT vs DECIMAL
u002du002d Qué pasa con FLOATnSELECT CAST(0.1 AS FLOAT) + CAST(0.2 AS FLOAT);nu002du002d Resultado: 0.30000001192092896 (no es 0.3)nnu002du002d DECIMAL lo calcula correctamentenSELECT CAST(0.1 AS DECIMAL(10,2)) + CAST(0.2 AS DECIMAL(10,2));nu002du002d Resultado: 0.30 (exactamente 0.30)

¿Cómo importa este pequeño error en la práctica? Imagina una tienda online que vende un artículo de 11,99 € y procesa 50.000 pedidos al mes:

  • Con FLOAT: Cada fila puede arrastrar un error tan pequeño como +0,000001, pero a lo largo de 50.000 filas y múltiples cálculos de IVA, las discrepancias de redondeo se acumulan. Multiplica por cientos de SKUs durante un año, y el balance se desvía en euros — suficiente para desencadenar una investigación de auditoría
  • Con DECIMAL: Cero desviación. Cada agregación cuadra al céntimo, siempre

«Es solo una millonésima de euro.» Cierto — pero en contabilidad, si los libros no cuadran al céntimo, alguien tiene que explicar por qué. «Usamos el tipo de columna equivocado» no es una respuesta que ningún auditor vaya a aceptar.

DECIMAL se declara como DECIMAL(M, D) donde M es el total de dígitos y D los decimales:

DECIMAL en la práctica
u002du002d DECIMAL(10,2): 10 dígitos en total, 2 decimalesnu002du002d Valor máximo: 99.999.999,99nnCREATE TABLE orders (n  id         INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,n  subtotal   DECIMAL(10,2) NOT NULL,  u002du002d Importe antes de impuestosn  tax_rate   DECIMAL(5,4)  NOT NULL,  u002du002d ej. 0.2100 (21% IVA)n  tax_amount DECIMAL(10,2) NOT NULL,  u002du002d Impuestosn  total      DECIMAL(10,2) NOT NULL   u002du002d Total finaln);
💡 Tip

DECIMAL y NUMERIC son sinónimos en el estándar SQL. MySQL, PostgreSQL y SQL Server los tratan de forma idéntica. Elige uno y sé consistente en todo tu código.

Dimensionar DECIMAL — Por qué DECIMAL(18,10) casi siempre es excesivo

Otro error frecuente es especificar una precisión excesiva: DECIMAL(18,10) o incluso DECIMAL(30,15) «por si acaso». Esto desperdicia almacenamiento y ralentiza las agregaciones.

El tamaño de almacenamiento de DECIMAL es proporcional a su número de dígitos. En MySQL, cada 9 dígitos consumen 4 bytes, con bytes extra para los dígitos restantes:

TipoAlmacenamiento (MySQL)Ejemplo de uso
DECIMAL(5,2)3 bytesPorcentajes (hasta 99,99 %)
DECIMAL(10,2)5 bytesPrecios (hasta 99.999.999,99 €)
DECIMAL(12,4)6 bytesTipos de cambio (ej. 1,3456)
DECIMAL(18,10)9 bytesExcesivo para la mayoría de aplicaciones

El enfoque correcto es partir del valor máximo e ir hacia atrás:

  • Precios de e-commerce: Si el precio más alto es de unos pocos millones de euros, DECIMAL(10,2) cubre hasta 99.999.999,99 €
  • Tasas de IVA: En España el tipo general es del 21 %. DECIMAL(5,4) admite hasta 99,9999 %
  • Porcentajes de descuento: 0–100 % cabe en DECIMAL(5,2)
  • Tipos de cambio: EUR/USD a 1,0845 — DECIMAL(12,4) ofrece margen de sobra
  • Criptomonedas: La unidad más pequeña de Ethereum (wei = 10⁻¹⁸ ETH) realmente necesita DECIMAL(36,18) — un caso raro donde la precisión extrema está justificada

Usar DECIMAL(18,10) para una columna de precios en retail es como imprimir una nota personal en un pliego de papel A0. Ajusta la precisión al tamaño justo y ahorrarás almacenamiento y acelerarás las consultas.

FLOAT / DOUBLE — Velocidad a costa de la exactitud

FLOAT y DOUBLE son tipos de punto flotante que representan decimales usando el formato binario IEEE 754. Esto les da una gran ventaja y una limitación inherente.

La ventaja es clara: unos fijos 4 bytes (FLOAT) u 8 bytes (DOUBLE) pueden representar un rango enorme de valores. Solo FLOAT cubre ±3,4 × 10³⁸, y el hardware de punto flotante de la CPU realiza la aritmética extremadamente rápido.

La limitación es que almacenan aproximaciones, no valores exactos. El decimal 0,1 se convierte en el binario infinito periódico 0,000110011001100… que debe redondearse para caber en un número finito de bits. Esta es la causa raíz del famoso problema «0,1 + 0,2 ≠ 0,3».

FLOAT es la elección adecuada cuando pequeños errores de redondeo no afectan al resultado:

  • Lecturas de temperatura: Un sensor industrial reporta 23,45 °C con una precisión intrínseca de ±0,1 °C. Un error de almacenamiento de ±0,0001 °C carece de importancia
  • Coordenadas GPS: Seis decimales en latitud/longitud corresponden a ~11 cm de precisión. DOUBLE mantiene hasta 15 dígitos significativos — precisión submilimétrica que supera con creces cualquier necesidad real
  • Features de machine learning: Los modelos de ML tienen millones o miles de millones de parámetros; un redondeo microscópico en un peso individual tiene un impacto despreciable en la precisión global
  • Simulaciones físicas: La dinámica de fluidos y el análisis estructural dependen de la velocidad de FLOAT, con el error controlado a nivel de algoritmo
  • Agregados estadísticos: Medias, desviaciones típicas y correlaciones se calculan a partir de datos que ya contienen ruido estadístico

La diferencia entre FLOAT y DOUBLE se reduce a precisión y almacenamiento:

TipoTamañoDígitos significativosCuándo elegirlo
FLOAT4 bytes~7Almacenamiento limitado, datos de sensores
DOUBLE8 bytes~15Alta precisión necesaria: GPS, cálculo científico

Guardar coordenadas GPS como FLOAT ofrece solo ~7 dígitos significativos — aproximadamente 11 m de precisión. Para una aplicación de mapas, DOUBLE (~15 dígitos, submilimétrico) es la opción clara. Por el contrario, guardar lecturas de sensores de temperatura como DOUBLE no tiene sentido cuando el propio sensor solo tiene una precisión de ±0,5 °C — FLOAT es más que suficiente.

FLOAT vs. DECIMAL — Guía rápida de decisión

En la práctica, necesitas tomar esta decisión de forma rápida y segura. Aquí tienes una tabla de referencia:

Caso de usoDECIMALFLOAT / DOUBLE
Precios, facturas, facturación✗ (nunca)
Tasas de impuestos, descuentos
Puntos de fidelización / millas✓ (si son fraccionarios)
Peso de inventario (kg, lb)
Temperatura / humedad
Coordenadas GPS✓ (DOUBLE)
Datos de sensores
Features de ML / scores
Valores estadísticos (media, etc.)

La regla general cabe en tres líneas:

  • ¿Hay dinero de por medio? → DECIMAL
  • ¿Medición o ciencia? → FLOAT / DOUBLE
  • ¿No estás seguro? → DECIMAL (mejor pecar de precavido)

Memoriza estas tres reglas y rara vez te equivocarás.

Cinco errores de diseño habituales

Los errores de tipo numérico suelen ser invisibles durante el desarrollo y solo afloran en producción. Estos son los cinco más frecuentes.

Error 1: Poner BIGINT en todas las columnas

La mentalidad de «más grande es más seguro» lleva a los equipos a poner BIGINT por defecto en cada columna entera. Como hemos visto, esto puede desperdiciar más de 1 GB por cada 100 millones de filas en una sola columna más índices. En 10 tablas con 3 columnas BIGINT cada una, eso supone unos 12 GB de almacenamiento desperdiciado — impactando directamente en los costes de hosting en la nube y en la eficiencia del buffer pool.

Error 2: Usar FLOAT para dinero

Este es el error más peligroso de la lista. A menudo pasa todos los tests unitarios porque los errores de redondeo son invisibles a pequeña escala. El problema aparece en producción cuando el volumen de transacciones crece: «La facturación mensual no coincide con los depósitos bancarios reales.» El análisis de causa raíz lleva días, y corregir retroactivamente datos financieros almacenados con FLOAT es extremadamente difícil.

Error 3: Sobredimensionar la precisión de DECIMAL

Definir DECIMAL(30,15) «por si acaso» desperdicia almacenamiento y ralentiza las consultas de agregación. Fuera de las criptomonedas (donde 18 decimales son realmente necesarios), muy pocos dominios de negocio requieren más de 4 decimales.

Error 4: No prever el desbordamiento de INT

Una tabla puede empezar con solo unos cientos de inserciones al día, pero el crecimiento puede ser exponencial. INT SIGNED llega hasta ~2.100 millones. Con AUTO_INCREMENT a 50.000 inserciones/día, eso son 117 años de margen — pero los volcados de datos de prueba, los huecos en los IDs y el crecimiento inesperado pueden consumir ese margen más rápido de lo esperado. Monitoriza tus marcas de agua de AUTO_INCREMENT regularmente.

Error 5: Tipos distintos en los JOIN

Si orders.user_id es INT pero users.id es BIGINT, cada JOIN dispara una conversión implícita de tipos. En MySQL, esto puede impedir que el optimizador use los índices, convirtiendo una consulta de milisegundos en un escaneo completo de tabla de varios segundos. Asegúrate siempre de que las columnas usadas en JOINs compartan exactamente el mismo tipo.

Tipos recomendados por caso de uso

Usa esta tabla de referencia rápida cuando diseñes nuevas tablas:

Propósito de la columnaTipo recomendadoNotas
ID de usuarioINT UNSIGNED4.200 millones son suficientes
ID de productoINT UNSIGNEDMismo razonamiento
ID de log / eventoBIGINT UNSIGNEDMiles de millones de filas al año
ID SnowflakeBIGINTValores inherentemente grandes
Precio de productoDECIMAL(10,2)Máx. 99.999.999,99 €
Tasa de IVADECIMAL(5,4)ej. 0.2100 (21 %)
Tasa de descuentoDECIMAL(5,2)ej. 15,50 %
Tipo de cambioDECIMAL(12,4)ej. 1,0845
Cantidad en stock (entera)INT UNSIGNEDNo necesita decimales
Peso (kg / lb)DECIMAL(8,3)ej. 12345,678
TemperaturaFLOATLa precisión del sensor es suficiente
GPS lat / lngDOUBLESe requiere alta precisión
Feature de MLFLOATVelocidad por encima de precisión
Puntos (enteros)INT UNSIGNEDSin fracciones
Puntos (fraccionarios)DECIMAL(10,2)Millas de aerolínea, etc.
Posición en rankingINT UNSIGNEDLos rankings no son negativos
Flag booleano (0/1)TINYINT UNSIGNEDLo que MySQL usa internamente para BOOLEAN
Código de estadoTINYINT o SMALLINTDimensiona según el rango de valores

Compartir una tabla como esta en tu equipo elimina la mayoría de debates sobre tipos durante las revisiones de código.

CREATE TABLE — Ejemplos del mundo real

Por último, aquí tienes tres definiciones de tablas listas para producción. Fíjate en cómo cada columna usa el tipo más pequeño adecuado.

Ejemplo 1: Productos de e-commerce

products.sql
CREATE TABLE products (n  id          INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,n  name        VARCHAR(255) NOT NULL,n  price       DECIMAL(10,2) NOT NULL DEFAULT 0.00,  u002du002d Dinero = DECIMALn  tax_rate    DECIMAL(5,4) NOT NULL DEFAULT 0.2100, u002du002d 21% IVA = 0.2100n  stock       INT UNSIGNED NOT NULL DEFAULT 0,       u002du002d Cantidad enteran  weight_kg   DECIMAL(8,3),                          u002du002d Peso para envíon  rating      FLOAT,                                 u002du002d Valoración median  is_active   TINYINT UNSIGNED NOT NULL DEFAULT 1,   u002du002d Flag booleanon  created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMPn) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Ejemplo 2: Logs de acceso

access_logs.sql
CREATE TABLE access_logs (n  id          BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, u002du002d Alto volumenn  user_id     INT UNSIGNED,               u002du002d Coincide con el tipo de users.idn  status_code SMALLINT UNSIGNED NOT NULL,  u002du002d HTTP 200, 404, 500...n  response_ms INT UNSIGNED,                u002du002d Tiempo de respuesta en msn  created_at  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,n  INDEX idx_user (user_id),n  INDEX idx_created (created_at)n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Ejemplo 3: Lecturas de sensores IoT

sensor_readings.sql
CREATE TABLE sensor_readings (n  id            BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,n  device_id     INT UNSIGNED NOT NULL,n  temperature   FLOAT,          u002du002d La precisión del sensor es suficienten  humidity      FLOAT,          u002du002d Ídemn  latitude      DOUBLE,         u002du002d GPS necesita alta precisiónn  longitude     DOUBLE,         u002du002d Ídemn  battery_pct   TINYINT UNSIGNED, u002du002d Batería 0-100%n  recorded_at   DATETIME(3) NOT NULL, u002du002d Precisión de milisegundosn  INDEX idx_device_time (device_id, recorded_at)n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Las tres tablas comparten un rasgo común: cada columna está definida con el tipo más pequeño que cumple su propósito. Los IDs escalan con INT o BIGINT según la necesidad, el dinero usa DECIMAL, las mediciones usan FLOAT/DOUBLE, y los flags usan TINYINT. Así es como luce un esquema bien diseñado.

Resumen — Elegir el tipo es ingeniería de rendimiento

Elegir un tipo numérico en SQL no es solo una decisión de formato. Afecta a la eficiencia de almacenamiento, rendimiento de índices, velocidad de consultas, exactitud de los datos y escalabilidad futura — todo a la vez.

Lo esencial en cuatro líneas:

  • Si cabe en un entero, usa un tipo entero (el más rápido, el más pequeño, cero errores)
  • INT para la mayoría de columnas, BIGINT para logs de alto volumen (el almacenamiento se duplica)
  • DECIMAL para dinero — sin excepciones (los errores de FLOAT son devastadores en finanzas)
  • FLOAT / DOUBLE para ciencia y mediciones (velocidad y rango donde la aproximación es aceptable)

Sobre todo, el principio rector es: elige el tipo más pequeño que cumpla con tus requisitos. Los tipos sobredimensionados desperdician almacenamiento, reducen la eficiencia de caché y ralentizan las consultas. Los tipos infradimensionados arriesgan el desbordamiento. Acertar significa estimar la naturaleza de tus datos (entero vs. decimal), el rango de valores, la tolerancia al error y la tasa de crecimiento durante la vida útil del sistema.

El diseño de tipos numéricos no es un trabajo glamuroso, pero hacerlo bien desde el primer día te ahorra degradación de rendimiento, inflado de almacenamiento e incidencias en producción a largo plazo. Cada vez que escribas un CREATE TABLE, pregúntate: «¿Es este tipo realmente el adecuado?» Solo ese hábito elevará la calidad de tu diseño de base de datos.

Preguntas frecuentes

P. ¿En qué debería pensar primero cuando no tengo claro qué tipo usar?

R. Empieza preguntándote: «¿Se puede representar este valor como un entero?» Si la respuesta es sí, ve con un tipo INT. Después pregúntate: «¿Tiene que ver con dinero?» Si es así, DECIMAL es la única respuesta. Todo lo demás con decimales — temperaturas, coordenadas, puntuaciones — apunta a FLOAT o DOUBLE. Sigue esta secuencia y el 95 % de las decisiones serán instantáneas.

P. ¿Lo complicado que es migrar de INT a BIGINT después?

R. El ALTER TABLE ... MODIFY COLUMN de MySQL puede cambiar el tipo, pero en tablas grandes bloquea la tabla durante minutos o incluso horas. Herramientas como pt-online-schema-change o gh-ost realizan la migración con prácticamente cero downtime, pero aun así requieren una planificación cuidadosa. Acertar con el tipo desde el principio siempre es más barato que corregirlo después.

P. PostgreSQL no soporta UNSIGNED — ¿qué hago?

R. Correcto. La solución estándar en PostgreSQL es usar una restricción CHECK (CHECK (id >= 0)) para forzar valores no negativos. Como el INT de PostgreSQL sigue llegando hasta ~2.100 millones, es suficiente para la mayoría de cargas de trabajo. Si realmente necesitas el rango de 4.200 millones, pasa a BIGINT.

P. ¿Cuánto afecta realmente el error de redondeo de FLOAT en la práctica?

R. FLOAT (4 bytes) tiene unos 7 dígitos significativos. Almacena 123456,789 en FLOAT y podrías recuperar 123456,7890625. Para datos de sensores o mediciones científicas — donde el propio instrumento tiene una precisión limitada — esto es irrelevante. Para cálculos financieros, significa facturas que se desvían un céntimo y totales mensuales que no cuadran. La regla es simple: nunca uses FLOAT para dinero.

P. ¿DECIMAL es realmente más lento que INT? ¿Cuánto?

R. En consultas con agregaciones pesadas (SUM, AVG sobre millones de filas), DECIMAL puede ser entre 1,2× y 2× más lento que INT. Para cargas de trabajo OLTP típicas — SELECTs e INSERTs individuales — la diferencia es despreciable. Algunos equipos almacenan precios como céntimos enteros (ej. 19,99 € → 1999) para ganar la velocidad de INT, pero esto se rompe en cuanto necesitas soporte multidivisa o cálculos por debajo del céntimo. Empezar con DECIMAL es la apuesta más segura a largo plazo.

Comments

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *