SQL vs NoSQL: cuándo usar cada una y por qué existen ambas
Mucha gente piensa que NoSQL vino a reemplazar SQL. No es así. Las bases relacionales y las NoSQL resuelven problemas distintos. Entender esa diferencia es clave para diseñar sistemas escalables, rápidos y mantenibles.
La pregunta clave
¿Por qué usaríamos NoSQL si SQL permite joins, relaciones y queries más potentes? Porque NoSQL sacrifica flexibilidad para ganar escalabilidad horizontal, throughput masivo y latencia predecible.
El cambio de mentalidad
En SQL pensás: "¿cómo relaciono entidades?". En NoSQL pensás: "¿cómo obtengo esta pantalla o endpoint con la menor cantidad de lecturas posibles?".
Regla práctica
Si necesitás flexibilidad y relaciones complejas → SQL. Si necesitás escala gigantesca y access patterns ultra definidos → NoSQL.
Qué es SQL realmente
Las bases SQL están diseñadas alrededor de:
- Relaciones entre entidades
- Integridad de datos
- Joins complejos
- Queries dinámicas
- Normalización
- Consistencia fuerte
Por eso herramientas como PostgreSQL son espectaculares para:
- ERPs
- Sistemas bancarios
- Backoffices
- Facturación
- Analytics
- Dashboards
SQL te deja hacer consultas extremadamente poderosas porque entiende relaciones.
Joins y modelo relacional
Flexibilidad máximaEn una base relacional, cada tabla representa una entidad distinta y las relaciones se conectan usando claves foráneas.
JOIN clásico
La base se encarga automáticamente de relacionar órdenes con usuarios.
SELECT
o.id,
u.name,
u.email
FROM orders o
JOIN users u
ON o.user_id = u.id
WHERE o.status = 'PAID';
DynamoDB y access patterns
Escala masivaBases como DynamoDB no están optimizadas para joins. Están optimizadas para responder extremadamente rápido a patrones de acceso específicos.
La gran desventaja: no hay joins
En SQL, si querés un usuario y sus órdenes, hacés un JOIN y listo.
En DynamoDB eso no existe del lado del servidor. Si modelás los datos
como en SQL (una tabla users y otra orders), para responder
"dame el usuario 123 y todas sus órdenes" tendrías que hacer:
- Una query a la tabla de usuarios.
- Otra query a la tabla de órdenes filtrando por
user_id. - Combinar los resultados en tu backend.
Eso es lento, caro y rompe la principal ventaja de NoSQL (latencia baja y predecible). Por eso el cambio de mentalidad: en vez de pensar:
"¿cómo relaciono usuarios y órdenes?"
pensás:
"¿cómo hago para obtener TODO lo necesario con una sola query?"
La solución: Single Table Design
La técnica clásica de DynamoDB es meter todas las entidades relacionadas en una sola tabla, compartiendo la misma partition key (PK). Así, una sola consulta trae todo lo que necesitás sin joins.
Single Table Design
El perfil del usuario y todas sus órdenes viven bajo la misma partition key
(USER#123). La sort key (SK) los diferencia.
PK SK
USER#123 PROFILE
USER#123 ORDER#1
USER#123 ORDER#2
USER#123 ORDER#3
Una sola query reemplaza al JOIN
Filtrando por PK = USER#123 traés perfil + órdenes en una sola lectura,
sin joins y con latencia constante.
response = table.query(
KeyConditionExpression=
"PK = USER#123"
)
¿Qué es throughput?
Métrica claveThroughput es la cantidad de operaciones que un sistema puede procesar por unidad de tiempo. En bases de datos se suele medir en:
- QPS — queries por segundo
- RPS — requests por segundo
- TPS — transacciones por segundo
- RCU / WCU en DynamoDB — read/write capacity units por segundo
Es importante no confundir throughput con latencia:
Latencia
- Cuánto tarda UNA operación en responder.
- Se mide en milisegundos.
- Ej: "este endpoint responde en 40 ms".
- Importa para la experiencia del usuario individual.
Throughput
- Cuántas operaciones podés hacer en paralelo por segundo.
- Se mide en ops/seg.
- Ej: "el sistema soporta 50.000 requests por segundo".
- Importa para soportar muchos usuarios al mismo tiempo.
Una analogía clásica: una autopista. La latencia es cuánto tarda un auto en cruzarla. El throughput es cuántos autos cruzan por minuto. Podés tener latencia baja pero throughput bajo (autopista corta de un solo carril) o latencia más alta pero throughput enorme (autopista larga de 10 carriles).
Escalamiento vertical vs horizontal
El corazón del tradeoffCuando una base de datos empieza a recibir más tráfico del que puede manejar, hay dos formas de hacerla más grande. Esa decisión es lo que separa el mundo SQL del mundo NoSQL.
Vertical (Scale Up)
- Una sola máquina más grande: más CPU, más RAM, más disco.
- No cambia la arquitectura, solo el hardware.
- Fácil de implementar: la app no se entera de nada.
- Mantiene consistencia fuerte y transacciones ACID sin esfuerzo.
- Límite físico: el servidor más grande del mundo sigue siendo finito.
- Caro: el costo crece exponencialmente, no lineal.
- Si esa máquina se cae, se cae todo (single point of failure).
Horizontal (Scale Out)
- Muchas máquinas chicas trabajando en paralelo (sharding / clustering).
- Los datos se reparten entre nodos por una partition key.
- Escala "infinito": agregás más nodos cuando hace falta.
- Tolerante a fallos: si un nodo muere, los demás siguen.
- Costo lineal: hardware commodity barato.
- Pierde joins fáciles y consistencia fuerte (teorema CAP).
- Más complejo de operar y de modelar.
¿Por qué SQL prefiere vertical?
Una base relacional garantiza ACID (Atomicity, Consistency, Isolation, Durability) y joins entre tablas. Para mantener eso, el motor necesita ver toda la data en un mismo lugar:
- Un JOIN entre
usersyordersrequiere leer ambas tablas de forma coordinada. Si están en servidores distintos, el JOIN se vuelve un problema de red distribuido (lento y costoso). - Las transacciones (
BEGIN ... COMMIT) necesitan bloquear filas. Distribuir locks entre máquinas implica protocolos complejos como two-phase commit, que matan la performance. - Las foreign keys exigen verificar integridad referencial en tiempo real. Eso es trivial en una sola máquina y muy caro entre muchas.
Por eso PostgreSQL, MySQL, Oracle y SQL Server escalan principalmente hacia arriba: le metés más RAM, mejores discos NVMe, más núcleos. Sí existen réplicas de lectura y soluciones de sharding (Citus, Vitess), pero son parches sobre un modelo que originalmente fue diseñado para vivir en un solo nodo.
¿Por qué NoSQL nació horizontal?
DynamoDB, Cassandra, MongoDB y compañía nacieron en empresas como Amazon, Facebook y Google donde una sola máquina jamás iba a alcanzar. Entonces el diseño parte de otra premisa:
- Los datos se reparten entre nodos usando una partition key. Cada query sabe a qué nodo ir.
- No hay joins server-side, así que no hace falta coordinar nodos para responder una consulta.
- Se acepta consistencia eventual a cambio de disponibilidad y partición tolerante (lado AP del teorema CAP).
- Si necesitás más capacidad, agregás nodos. La base redistribuye los datos sola.
| Aspecto | Vertical (SQL) | Horizontal (NoSQL) |
|---|---|---|
| Forma de crecer | Máquina más potente | Más máquinas en paralelo |
| Tope máximo | Limitado por el hardware | Prácticamente ilimitado |
| Costo | Exponencial | Lineal |
| Tolerancia a fallos | Single point of failure | Alta (replica entre nodos) |
| Consistencia | Fuerte (ACID) | Eventual (BASE) |
| Joins | Naturales | No existen server-side |
Por qué SQL no está preparado para datos jerárquicos y NoSQL sí
Hierarchical data storageDatos jerárquicos = datos con forma de árbol o anidados: un usuario que tiene un perfil, que tiene direcciones, que tienen contactos, que tienen preferencias… O un comentario que tiene respuestas, que tienen sub-respuestas, etc.
El problema en SQL
El modelo relacional es plano por naturaleza: tablas con filas y columnas. Para representar una jerarquía hay que romper el árbol en varias tablas conectadas por foreign keys. Después, para reconstruirlo, hay que hacer múltiples JOINs o consultas recursivas.
Reconstruir un usuario completo en SQL
Hay que unir varias tablas solo para obtener un objeto anidado.
SELECT u.*, p.*, a.*, c.*
FROM users u
LEFT JOIN profiles p ON p.user_id = u.id
LEFT JOIN addresses a ON a.user_id = u.id
LEFT JOIN contacts c ON c.address_id = a.id
WHERE u.id = 123;
Limitaciones reales de SQL frente a jerarquías:
- Schema rígido: cada nivel del árbol necesita su propia tabla y migraciones para cambiar.
- Profundidad variable: si un comentario puede tener N niveles de respuestas, tenés que usar recursive CTEs (
WITH RECURSIVE), que son lentas y difíciles de mantener. - Resultado tabular: el JOIN devuelve una tabla aplanada con datos repetidos. Hay que reconstruir el árbol en código.
- Escala mal con anidamiento profundo: cada nivel = otro JOIN = más latencia.
Por qué NoSQL lo resuelve naturalmente
Las bases de documentos (MongoDB, DynamoDB, Firestore) guardan el árbol completo como un único documento. La estructura del dato en la base es la misma que en tu app.
El mismo usuario como documento anidado
Un solo findOne() y tenés todo el árbol.
{
"_id": 123,
"name": "Pamela",
"profile": {
"bio": "Backend dev",
"avatar": "..."
},
"addresses": [
{
"city": "BA",
"contacts": [
{ "type": "phone", "value": "+54..." },
{ "type": "email", "value": "p@x.com" }
]
}
]
}
Por qué NoSQL gana acá:
- Schema flexible: cada documento puede tener una forma distinta. Agregar un campo no requiere migración.
- Una sola lectura: traer el árbol completo es O(1) consultas, no O(n) joins.
- Profundidad arbitraria: arrays dentro de objetos dentro de arrays. Sin tablas extra.
- Localidad de datos: al estar todo junto en disco, una sola lectura física trae la jerarquía completa. Esto encaja perfecto con el sharding horizontal: el árbol entero vive en un nodo.
- Mismo formato app ↔ DB: JSON entra, JSON sale. Sin ORMs que reconstruyan objetos.
La diferencia REAL entre SQL y NoSQL
No existe magiaSQL
- Joins complejos
- Queries dinámicas
- Relaciones fuertes
- Integridad referencial
- Más flexible para consultar
- Ideal para reporting y analytics
- Normalización
- Escala vertical natural
NoSQL
- Escalabilidad horizontal extrema
- Latencia muy baja
- Throughput masivo
- Alta concurrencia
- Diseño orientado a access patterns
- Denormalización
- Datos jerárquicos nativos
- Schema flexible
Por qué TikTok o Netflix usan NoSQL
Millones de requestsEl verdadero diferencial de NoSQL no es solamente "una query más rápida". El diferencial es mantener latencias bajas incluso con tráfico monstruoso.
| Problema | SQL | NoSQL |
|---|---|---|
| Millones de usuarios concurrentes | Más difícil de escalar | Escalabilidad horizontal natural |
| Joins complejos | Excelente | Malo |
| Latencia predecible | Depende de la query | Muy buena |
| Queries arbitrarias | Excelente | Muy limitado |
| Feeds y timelines | Posible | Excelente |
| Datos jerárquicos / anidados | Requiere muchos JOINs | Nativo (documentos) |
La parte difícil de NoSQL
Modelado complejoMucha gente cree que NoSQL es "más simple". En realidad, diseñar bien DynamoDB puede ser muchísimo más difícil que diseñar SQL.
Porque necesitás pensar:
- Cómo se va a leer la información
- Qué endpoints existen
- Qué pantallas consume el frontend
- Qué datos deben duplicarse
- Cómo evitar múltiples queries
Cuando no podés meter todo en una sola query
A veces el access pattern no encaja en un Single Table Design (por ejemplo:
necesitás un listado de órdenes de distintos usuarios). Como NoSQL
no tiene joins server-side, la solución es traer las órdenes
primero y después resolver la "unión" desde el backend con un
BatchGetItem: pedís de una vez todos los usuarios involucrados y los
mergeás en memoria.
Join en memoria con batch
1) Traemos las órdenes. 2) Juntamos los user_id. 3) Pedimos
todos los usuarios en un solo batch. El "join" lo hace el backend, no la base.
orders = get_orders()
user_ids = [
o["user_id"]
for o in orders
]
users = batch_get_users(user_ids)
Entonces… cuál deberías aprender primero
Si estás aprendiendo backend, SQL debería ser tu prioridad.
Porque:
- Te enseña modelado de datos
- Te obliga a entender relaciones
- Es el estándar de la industria
- Se usa en casi todos los sistemas empresariales
Después, cuando entiendas escalabilidad y arquitectura distribuida, NoSQL empieza a tener muchísimo más sentido.
Cierre rápido
- SQL Excelente para relaciones, joins y queries complejas. Escala vertical.
- NoSQL Excelente para throughput masivo y latencia predecible. Escala horizontal.
- DynamoDB No tiene joins server-side. El diseño gira alrededor de access patterns.
- Tradeoff Más flexibilidad vs más escalabilidad.
- Realidad Las empresas grandes usan ambas al mismo tiempo.
Conclusión
SQL y NoSQL no compiten directamente. Son herramientas distintas para problemas distintos.
SQL te da relaciones, consistencia y flexibilidad, y crece haciendo más grande UNA máquina. NoSQL te da escalabilidad horizontal, throughput enorme, datos jerárquicos nativos y latencias muy bajas incluso bajo tráfico gigante, repartiendo el trabajo entre MUCHAS máquinas.
El verdadero seniority no está en elegir "la mejor base de datos". Está en entender qué tradeoffs estás aceptando cuando diseñás un sistema.