SQL distribuido y NewSQL: la próxima generación de bases de datos

Durante décadas, el mundo de las bases de datos estuvo dividido en dos bandos: **bases de datos relacionales** (PostgreSQL, MySQL) con una fuerte consistencia pero escalabilidad limitada, y **bases de datos NoSQL** (MongoDB, Cassandra) con escalabilidad horizontal pero una consistencia más débil y capacidades de consulta limitadas.
Introducción
Durante décadas, el mundo de las bases de datos estuvo dividido en dos bandos: bases de datos relacionales (PostgreSQL, MySQL) con una fuerte consistencia pero escalabilidad limitada, y bases de datos NoSQL (MongoDB, Cassandra) con escalabilidad horizontal pero una consistencia más débil y capacidades de consulta limitadas.
SQL distribuido (también llamado NewSQL) cierra esta brecha. Proporciona todo el poder de SQL (transacciones ACID, uniones, claves externas y herramientas familiares) en una arquitectura distribuida y escalable horizontalmente. El resultado: la coherencia y el poder de consulta de una base de datos relacional con la escalabilidad de NoSQL.
El espectro de la base de datos
Strong Consistency
▲
│ ┌───────────────────────┐
│ │ Distributed SQL │
│ │ (CockroachDB, │
│ │ YugabyteDB, │
│ │ Google Spanner) │
│ └───────────────────────┘
│
│ ┌──────────────┐ ┌──────────────────┐
│ │ Traditional │ │ Traditional │
│ │ SQL │ │ NewSQL │
│ │ (PostgreSQL,│ │ (Vitess, TiDB) │
│ │ MySQL) │ │ │
│ └──────────────┘ └──────────────────┘
│
│ ┌──────────────────┐
│ │ NoSQL │
│ │ (Cassandra, │
│ │ DynamoDB, │
│ │ CosmosDB) │
│ └──────────────────┘
└────────────────────────────────────────────────────
Horizontal Scalability ──────►
¿Qué es SQL distribuido?
Características principales
| Característica | Descripción |
|---|---|
| Interfaz SQL | Soporte completo de SQL: JOIN, subconsultas, agregaciones, funciones de ventana |
| Transacciones ACIDAS | Serializable o aislamiento de instantáneas entre nodos |
| Escala horizontal | Agregue nodos sin tiempo de inactividad, los datos se reequilibran automáticamente |
| fragmentación automática | Datos distribuidos automáticamente entre nodos |
| Replicación | Replicación síncrona para mayor durabilidad (RPO=0) |
| Alta disponibilidad | Conmutación por error automática, sin intervención manual |
| Geodistribución | Los datos pueden abarcar varias regiones con una latencia <50 ms |
Arquitecturas SQL distribuidas
Google Spanner: el pionero
┌──────────────────────────────────────────┐
│ Spanner Global Architecture │
├──────────────────────────────────────────┤
│ Zone 1 (us-east1) Zone 2 (europe-west)│
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Leader Node │ │ Follower Node│ │
│ │ ┌────────┐ │ │ │ │
│ │ │ Spanner│ │ │ │ │
│ │ │ Server │ │ │ │ │
│ │ └────────┘ │ │ │ │
│ └──────────────┘ └──────────────┘ │
├──────────────────────────────────────────┤
│ TrueTime API (GPS + Atomic) │
│ Clock synchronization < 7ms │
└──────────────────────────────────────────┘
Innovación clave: API TrueTime: sincronización de reloj atómico y GPS que proporciona una incertidumbre de reloj limitada. Esto permite la coherencia externa (linealización) entre nodos distribuidos globalmente.
CockroachDB: código abierto inspirado en Spanner
┌─────────────────────────┐
│ SQL Gateway │
│ (Any node can serve) │
└──────────┬──────────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ Node 1 │ │ Node 2 │ │ Node 3 │
│ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │
│ │ Range A│ │ │ │ Range A│ │ │ │ Range A│ │
│ │ (LEADER)│ │ │(FOLLOWER│ │ │(FOLLOWER│ │
│ └───────┘ │ │ └───────┘ │ │ └───────┘ │
│ ┌───────┐ │ │ ┌───────┐ │ │ ┌───────┐ │
│ │ Range B│ │ │ │ Range B│ │ │ │ Range B│ │
│ │(FOLLOWER│ │ │ (LEADER)│ │ │(FOLLOWER│ │
│ └───────┘ │ │ └───────┘ │ │ └───────┘ │
└───────────┘ └───────────┘ └───────────┘
Cómo funciona CockroachDB:
- Los datos se dividen en rangos (64 MB de forma predeterminada, similar a las divisiones de Spanner).
- Cada rango se replica 3 veces (configurable) en todos los nodos.
- Una réplica es el arrendatario (maneja lecturas y escrituras).
- El Consenso de balsa garantiza la coherencia entre las réplicas.
- Cualquier nodo puede atender consultas: la puerta de enlace SQL se dirige al rango correcto.
YugabyteDB: compatible con PostgreSQL
YugabyteDB está diseñado para la compatibilidad con PostgreSQL a nivel de protocolo de conexión:
-- This is standard PostgreSQL syntax — it just works
CREATE TABLE orders (
id UUID DEFAULT gen_random_uuid(),
customer_id UUID NOT NULL,
total NUMERIC(10,2) NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
created_at TIMESTAMPTZ DEFAULT NOW(),
PRIMARY KEY (id)
);
-- Distributed ACID transaction across nodes
BEGIN;
INSERT INTO orders (customer_id, total, status)
VALUES ($1, $2, 'pending');
UPDATE inventory SET quantity = quantity - 1
WHERE product_id = $3 AND quantity > 0;
COMMIT;
-- Full PostgreSQL ecosystem compatibility
-- Supports: pgAdmin, Prisma, DBeaver, all standard drivers
Comparación de SQL distribuido
| Característica | CucarachaDB | YugabyteDB | TiDB | llave inglesa |
|---|---|---|---|---|
| Compatibilidad | PostgreSQL (85%) | PostgreSQL (95%+) | mysql | propietario |
| Consistencia | Serializable | Serializable | Aislamiento de instantáneas | Consistencia externa |
| Replicación | balsa | balsa | balsa | Paxos |
| Geodistribución | si | si | si | si |
| fragmentación automática | Sí (por rango) | Sí (por hash/rango) | Sí (por rango) | Sí (por división) |
| Índices secundarios | Global (distribuido) | Global + Local | Global + Local | Mundial |
| Claves externas | si | si | si | si |
| CDC | Sí (fregadero Kafka) | Sí (Kafka, Elástico) | Sí (TiCDC) | Sí (Pub/Sub) |
| Licencia | BSL (fuente disponible) | apache 2.0 | apache 2.0 | propietario |
| Administrado en la nube | Nube CucarachaDB | YugabyteDB administrado | Nube TiDB | Llave de nube |
| Autoanfitrión | si | si | si | No |
Cuándo utilizar SQL distribuido
Casos de uso ideales
| Caso de uso | Por qué SQL distribuido | Ejemplo |
|---|---|---|
| Aplicaciones SaaS globales | Los usuarios de todo el mundo necesitan baja latencia y una gran coherencia | Cuentas de usuario multirregionales |
| Sistemas financieros | Transacciones ACID entre fragmentos, sin pérdida de datos | Procesamiento de pagos, libro mayor |
| Plataformas de comercio electrónico | Inventario, pedidos, carros: todo necesita coherencia | Picos de tráfico del Viernes Negro |
| Juegos | Estado del jugador, tablas de clasificación, transacciones. | Multijugador entre regiones |
| Series temporales de IoT + metadatos | SQL para análisis de datos distribuidos | Telemetría de flota con uniones |
Cuándo NO utilizar SQL distribuido
| Escenario | ¿Por qué? | Mejor alternativa |
|---|---|---|
| Búsquedas simples de clave-valor | Gastos generales de transacciones distribuidas no justificados | Redis, DynamoDB |
| Región única, datos pequeños | Complejidad no necesaria | PostgreSQL |
| Búsqueda de texto completo | No diseñado para indexación de texto | búsqueda elástica |
| Recorridos de gráficos | Las UNIONES en relaciones profundas son lentas | neo4j |
| Rendimiento de escritura muy alto (>100 000 escrituras/seg/nodo) | Los gastos generales de consenso pueden ser demasiado altos | Casandra, ScyllaDB |
Estrategias de distribución de datos
Fragmentación basada en rango (CockroachDB, Spanner)
-- Data is split by primary key ranges
Table: orders
Range 1: PK '00000000' to '3fffffff' → Node 1 (LEADER) + Node 2, Node 3
Range 2: PK '40000000' to '7fffffff' → Node 2 (LEADER) + Node 1, Node 3
Range 3: PK '80000000' to 'bfffffff' → Node 3 (LEADER) + Node 1, Node 2
Range 4: PK 'c0000000' to 'ffffffff' → Node 1 (LEADER) + Node 2, Node 3
Pros: Escaneos de rango eficientes, buenos para claves secuenciales. Contras: Escribe puntos de acceso si se insertan claves secuenciales (resuelto mediante índices fragmentados).
Fragmentación basada en hash (YugabyteDB)
-- Hash-sharded primary key
CREATE TABLE orders (
id UUID DEFAULT gen_random_uuid(),
customer_id UUID,
total NUMERIC,
PRIMARY KEY (id HASH)
);
-- Data distribution by hash
Hash('00000000-...') = 0.23 → Tablet 1 → Node 1
Hash('11111111-...') = 0.67 → Tablet 2 → Node 2
Hash('22222222-...') = 0.12 → Tablet 3 → Node 3
Pros: Distribución uniforme de datos, sin puntos calientes. Contras: Los escaneos de rango en toda la mesa son ineficientes.
Funciones clave de SQL distribuido
Transacciones Distribuidas (2PC + Balsa)
-- This transaction spans multiple nodes
BEGIN;
UPDATE account_a SET balance = balance - 100 WHERE id = 'A';
UPDATE account_b SET balance = balance + 100 WHERE id = 'B'; -- Different node
COMMIT;
-- Under the hood:
-- 1. Transaction coordinator (any node) acquires locks
-- 2. Prepares both participants
-- 3. Raft commits the transaction record
-- 4. COMMIT acknowledged to client
-- All-or-nothing — guaranteed ACID
Índices secundarios globales
Los propios índices se distribuyen entre nodos:
CREATE INDEX idx_orders_customer ON orders (customer_id);
-- Query that uses the distributed index:
SELECT * FROM orders WHERE customer_id = $1;
-- 1. Routes to any node
-- 2. Node looks up customer_id in distributed index
-- 3. Index returns primary keys → fetch from correct ranges
-- 4. Returns results
Migraciones de esquemas en línea
SQL distribuido admite cambios de esquema sin tiempo de inactividad:
-- Add a column — non-blocking
ALTER TABLE orders ADD COLUMN discount NUMERIC(5,2) DEFAULT 0.00;
-- Create index — non-blocking (background build)
CREATE INDEX CONCURRENTLY idx_orders_date ON orders (created_at);
Cambiar captura de datos (CDC)
Transmita los cambios de la base de datos a los sistemas posteriores:
-- CockroachDB CDC
CREATE CHANGEFEED FOR TABLE orders, payments
INTO 'kafka://kafka-cluster:9092'
WITH updated, resolved, min_checkpoint_frequency = '5s';
-- YugabyteDB CDC connector
# Deploy to Kafka Connect
{
"name": "yb-cdc-connector",
"config": {
"connector.class": "io.yugabyte.cdc.YBChangeDataCaptureConnector",
"database.hostname": "yb-1.example.com",
"database.port": "5433",
"table.include.list": "public.orders"
}
}
Consideraciones operativas
Topologías de implementación
Región única (3 nodos):
replication:
factor: 3
constraints:
- "+region=us-east-1: 3"
# All data in one region, 3 copies, survives 2 node failures
Multirregión (fallo de región de supervivencia):
replication:
factor: 3
constraints:
- "+region=us-east-1: 1"
- "+region=us-west-1: 1"
- "+region=eu-west-1: 1"
# One copy in each region, survives any single region failure
# Write latency: round-trip to the farthest region
Multirregión con quórum cercano (para escrituras de baja latencia):
replication:
factor: 5
constraints:
- "+region=us-east-1: 3" # 3 copies here
- "+region=us-west-1: 1" # 1 copy for DR
- "+region=eu-west-1: 1" # 1 copy for DR
# Write quorum = 3, achievable within us-east-1
# Write latency = intra-region
Expectativas de latencia
| Topología | Latencia de escritura (p50) | Leer Latencia (p50) |
|---|---|---|
| Nodo único | 1-5 ms | 0,5-2 ms |
| 3 nodos, misma región | 5-15 ms | 1-5 ms |
| 3 nodos, 3 regiones (EE. UU., UE, APAC) | 100-300 ms | 5-50 ms (más cercano) |
| 5 nodos, 2 regiones (quorum cerrado) | 5-15 ms | 1-5 ms |
Migración desde PostgreSQL/MySQL
Estrategia: NoSQL a SQL (distribuido)
Phase 1: Evaluate
- Identify tables that need horizontal scaling
- Assess which queries cross shards
- Plan sharding key
Phase 2: Migrate schema
- Convert CREATE TABLE statements
- Choose primary key strategy (hash vs. range)
- Handle sequences (use UUIDs instead of SERIAL)
Phase 3: Migrate data
- Use CDC or batch export/import
- Verify consistency
- Set up replication from old DB
Phase 4: Cut over
- Point application to new DB
- Monitor performance
- Keep old DB as rollback target for 1 week
Problemas comunes de migración
-- PostgreSQL → CockroachDB
-- ❌ Sequences (not distributed)
SERIAL PRIMARY KEY → UUID DEFAULT gen_random_uuid()
-- ❌ Array functions not supported
array_agg(DISTINCT x) → json_agg(DISTINCT x) -- workaround
-- ❌ Long-running queries
-- Solution: add index or query hint
-- ❌ Cross-database queries (CockroachDB)
-- Each cluster = one database, no cross-DB queries
Conclusión
SQL distribuido representa la convergencia de dos décadas de evolución de bases de datos, combinando la confiabilidad y expresividad de SQL con la elasticidad y resistencia de los sistemas distribuidos.
Conclusiones clave
- Utilice SQL distribuido cuando necesite semántica de SQL pero haya superado un solo nodo.
- No apto para implementaciones pequeñas: PostgreSQL con réplicas de lectura es más sencillo y económico.
- Elija por compatibilidad: YugabyteDB para PostgreSQL, TiDB para MySQL, CockroachDB para nuevos proyectos.
- Planifique la latencia: las transacciones distribuidas tienen gastos generales. Comparar antes de comprometerse.
- Supervise cuidadosamente: esté atento a rangos elevados, consultas lentas y retrasos en la replicación.
Marco de decisión
Q: Do you need horizontal write scaling?
├─ Yes
│ Q: Do you need ACID across all data?
│ ├─ Yes → Distributed SQL (CockroachDB, Spanner)
│ └─ No → NoSQL (Cassandra, DynamoDB)
└─ No
Q: Do you need SQL features (joins, aggregations)?
├─ Yes → PostgreSQL
└─ No → Key-value or document store
SQL distribuido es la arquitectura de base de datos para la era global nativa de la nube: aplicaciones que deben funcionar en todas partes, con una gran coherencia y sin concesiones.
Artículos destacados

6 patrones de programación que aprendí de ingenieros senior

Crea un asistente privado de notas con IA
Convierte notas Markdown en un asistente consultable sin exponer borradores privados.

Automatiza la extracción de datos de facturas con OCR
Crea un flujo que lee facturas, extrae campos y marca valores dudosos para revisión.
Comentarios
0 comentariosTodavía no hay comentarios aprobados. Las respuestas nuevas pueden esperar moderación.