
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.
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.
Strong Consistency
▲
│ ┌───────────────────────┐
│ │ Distributed SQL │
│ │ (CockroachDB, │
│ │ YugabyteDB, │
│ │ Google Spanner) │
│ └───────────────────────┘
│
│ ┌──────────────┐ ┌──────────────────┐
│ │ Traditional │ │ Traditional │
│ │ SQL │ │ NewSQL │
│ │ (PostgreSQL,│ │ (Vitess, TiDB) │
│ │ MySQL) │ │ │
│ └──────────────┘ └──────────────────┘
│
│ ┌──────────────────┐
│ │ NoSQL │
│ │ (Cassandra, │
│ │ DynamoDB, │
│ │ CosmosDB) │
│ └──────────────────┘
└────────────────────────────────────────────────────
Horizontal Scalability ──────►
| 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 |
┌──────────────────────────────────────────┐
│ 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.
┌─────────────────────────┐
│ 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:
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
| 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 |
| 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 |
| 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 |
-- 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).
-- 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.
-- 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
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
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);
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"
}
}
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
| 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 |
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
-- 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
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.
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.
Todavía no hay comentarios aprobados. Las respuestas nuevas pueden esperar moderación.